attribute 和 property 是 Web 开发中,比较容易混淆的概念,而对于 value,因其特殊性,更易困惑,本文尝试做一下梳理和例证

attribute 和 property 的概念

简单的说,attribute 是元素标签的属性,property 是元素对象的属性,例如:

<input id="input" value="test value">
<script>
let input = document.getElementById('input');
console.log(input.getAttribute('value')); // test value
console.log(input.value); // test value
</script>
  • input 的 value attribute 是通过标签里的 value="test value" 定义的,可以通过 input.getAttribute('value') 获取,可以通过 input.setAttribute('value', 'New Value') 更新
  • input 的 value property 可通过 input.value 获取和更新,初始值是与 attribute 中的赋值一致的

attribute 和 property 的绑定

如果在最开始的时候,更新 attribute value 的值,property 的值也会随之改变

但是更新 property value 的值(在文本框输入或给 input.value 赋新值 ),attribute 的值不会随之改变,而且此时再更新 attribute 的值,property 的值也不再随之改变,如此动画所示,也可访问此页面尝试进行操作

这其实是脏值标记(dirty value flag)在起作用,dirty value flag 的初始值为 false,即 attribute value 的更新默认会改变对应的 property value,但是一旦用户交互修改了 property value,dirty value flag 的值就变为 true,即attribute value 的更新就不会改变对应的 property value 了

所以在实际项目中,我们一般都是在处理作为 property 的 value

Vue.js 对 value 的处理

一般情况使用 :value

Vue.js 的 v-bind,一般情况下是在处理 attribute,如果要作为 property 处理的话,需要加上 .prop

不过 v-bind:value 却大都默认为处理 property 值,因为被强制转化了,例如:

<input id="input" :value="'test value'" >
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let input = new Vue({
el: '#input',
mounted () {
console.log(this.$el.getAttribute('value')); // null
console.log(this.$el.value); // test value
console.log(this._vnode.data) // {attrs: {id: "input"}, domProps: {value: "test value"}}
}
});
</script>

可见,Vue.js 将 value 作为 VNode 的 data 中的 domProps 的属性,而不是 attrs 的属性,所以挂载后会成为作为 property 的 value

在 Vue.js 源码中,强制转化 property 的处理如下:

// src/compiler/parser/index.js
function processAttrs (el) {
...
if ((modifiers && modifiers.prop) || (
!el.component && platformMustUseProp(el.tag, el.attrsMap.type, name)
)) {
addProp(el, name, value, list[i], isDynamic)
} else {
addAttr(el, name, value, list[i], isDynamic)
}

其中 platformMustUseProp 在 web 平台的定义如下:

// src/platforms/web/util/attrs.js
const acceptValue = makeMap('input,textarea,option,select,progress')
export const mustUseProp = (tag: string, type: ?string, attr: string): boolean => {
return (
(attr === 'value' && acceptValue(tag)) && type !== 'button' ||
(attr === 'selected' && tag === 'option') ||
(attr === 'checked' && tag === 'input') ||
(attr === 'muted' && tag === 'video')
)
}

由上可知,类型不为 button 的 input, textarea, option, select, progress 的 value 会强制作为 property,而不需要设置为 :value.prop

例如 textarea 标签,其本身其实并不支持 value attribute,所以以下代码中的 value 的值并不会显示在多行文本框中

<textarea value="test value"></textarea>

但是在 Vue.js 中, 以下代码能成功绑定到 value property 并显示在多行文本框中

<textarea :value="'test value'"></textarea>

特殊情况使用 :value.prop

以上 Vue.js 源码需要注意的还有,强制作为 property, 还要满足 !el.component,即不为动态组件,因为动态组件的 el.component 的值为其 is attribute 的值

即动态组件的的 v-bind 默认都是作为 attribute的,如果要作为 property,就要使用 .prop,例如:

<div id="app">
<component :is="element" :value.prop="'test value'"></component>
<button @click="change">Change</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
element: 'input'
},
methods: {
change () {
this.element = 'input' === this.element ? 'textarea' : 'input';
}
}
});
</script>

如果以上 component 中,删除 :value.prop 的 .prop,切换到 textarea 时,其值就不会显示在多行文本框中,可以在此页面点击切换标签查看

总结

  • 作为 attribute 和 property 的 value 的绑定关系会在用户交互更新值后失效
  • Vue.js 一般使用 :value 即可让 value 作为 property
  • Vue.js 动态模版需要使用 :value.prop 才可让 value 作为 property

最新文章

  1. subline text3 使用总结
  2. 抓取网页内容生成kindle电子书
  3. hiho一下120周 后缀数组一&#183;重复旋律
  4. Selenium2学习-036-WebUI自动化实战实例-034-JavaScript 在 Selenium 自动化中的应用实例之六(获取 JS 执行结果返回值)
  5. 向Array中添加快速排序
  6. easyui datagrid 的分页刷新按钮
  7. jQuery EasyUI 数据网格 - 启用行内编辑(转自http://www.runoob.com/jeasyui/jeasyui-datagrid-datagrid12.html)
  8. Windows下用Git下载android源码 转载
  9. Weui 微信网站开发样式插件使用教程
  10. Android-UGallery
  11. Unity3d 真实的植物渲染
  12. EXCEL随机密码生成函数
  13. 3. 编写Java应用程序,定义Animal类,此类中有动物的属性:名称 name,腿的数量legs,统计动物的数量 count;方法:设置动物腿数量的方法 void setLegs(),获得腿数量的方法 getLegs(),设置动物名称的方法 setKind(),获得动物名称的方法 getKind(),获得动物数量的方法 getCount()。定义Fish类,是Animal类的子类,统计鱼的数量
  14. 201521123024 《Java程序设计》第11周学习总结
  15. 跨平台移动APP开发进阶(三)hbuilder+mui mobile app 开发心酸路
  16. [Leetcode]674. Longest Continuous Increasing Subsequence
  17. [Socket]Socket聊天小程序
  18. 【PyQt5-Qt Designer】QProgressBar() 进度条
  19. HDu4794 斐波那契循环节
  20. 【sping揭秘】10、SpringIOC容器扩展

热门文章

  1. 用canvas实现简单的下雪效果
  2. https信任库采坑记
  3. 用户HTTP请求过程简单剖析
  4. codeigniter框架的使用感受和注意事项
  5. 解决挖矿病毒【Xmrig miner 】CPU 100%服务器卡死问题
  6. go package 学习笔记 —— strconv(string与其他基本数据类型(int, float, bool)的转换)
  7. C语言程序设计(二) C数据类型
  8. js 随机产生100个0~1000之间的整数
  9. forEach 循环数组 # for in 循环对象 key # for of 循环对象 value
  10. 通过xshell远程部署