背景
最近使用element框架的时候用到inputNumber,需要渲染初始化数据并在数据修改后也能更新原数据。(下面的scope.row的数据源是在data里返回)
可是它的change事件只能传入最后修改值作参数,那我怎么修改原数据。然后我纠结了很久,突然想起这其实不就是表单控件的双向绑定吗..然后我修改为下面代码,成功了..
莫名有点生气还是要保持微笑:) 不过其实我是弄混了property和attribute的概念
除此以外我对数据的双向绑定还有vue的响应式原理概念的模糊不清,所以现在来捋一捋
首先,attribute 和 property 有什么不同?
For a given DOM node object, properties are the properties of that object, and attributes are the elements of the attributes property of that object.
对于一个DOM节点(object)来说,attributes也是object的其中一个property,而attributes就是attribute的集合。
When a DOM node is created for a given HTML element, many of its properties relate to attributes with the same or similar names, but it’s not a one-to-one relationship.
当DOM节点生成对应的HTML元素后,它的很多properties就会和它相同(似)名字的attributes有关,但并不都是一一对应关系。
我们看看下面一段html代码会可能比较容易理解一点~<input id="the-input" type="text" value="Name:">
这个DOM节点有id、type、value和其他properties。
- id property 反映到 id attributey,且一一对应
- type property
- 若为已知值,同上
- 否则,如当type=”foo”,foo不是输入的有效类型,则该type attribute为foo,而该type property为type property默认值text,即
theInput.getAttribute("type") // foo
,而theInput.type //text
- value property
theInput.value
为随着输入值改变而改变,即当前值theInput.getAttribute("value")
一直为Name:,即初始值
其实看到这里,可能很多人都会有一种感觉,property更趋于某object的共性(代表着内部专属的意义),而attribute则是我们主观给它加的特性(人为的拓展)
v-bind
绑定的到底是什么?
现在我们看回本文背景中第一条代码,其中的:value
其实是v-bind:value
的缩写。
而文档对v-bind
的用法是这样说的:
动态地绑定一个或多个特性,或一个组件 prop 到表达式。
所以我更觉得v-bind
绑定的是attribute,给组件传prop就是一个很明显的例子
1 <myComponent :yy="someprop"></mycomponent>
因为这个yy属性真的是我们yy出来的,因为我们在使用一个我们自定义的组件,给它传送的属性自然也是我们自定义出来的,我们赋予它意义并通过它其创造更大的意义。
因此,v-bind默认绑定的就是attribute,而v-bind:value
绑定的是value attribute,即初始值。
v-bind有三个修饰符:.prop
、.camel
、.sync
,
当加上.prop
的时候就是用来绑定DOM property。
看到这里,应该看得出v-bind并不是用来实现数据双向绑定的。
不过,你以为的数据双向绑定就是真的数据双向绑定吗(嗯?)
数据的双向绑定
数据初始化绑定(vue实例属性(在data定义)初始化输入框的原始值, 并渲染文本节点)-》响应式的数据绑定(输入框的value变化会影响与其绑定的vue实例属性) -》订阅/发布模式(观测者检测到数据变化,告知文本节点,节点则相应更新)
时间太晚了+ +… 具体原理稍后再补
vue的响应式系统
data对象里面的属性才是响应式的。
Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
但什么是响应式呢?
当你尝试修改一个数据的时候,触发其有关的视图会更新,实现数据的双向绑定。否则,在其他使用了该数据的地方,将不会进行更新。- 若某属性没有在data对象上声明,不能使用
vue实例.newProperty=xxx
成为响应式属性。因为此时vue实例已经创建,Vue 不允许在已经创建的实例上动态添加新的根级响应式属性。
但可以使用下面两种方法:- vue全局set方法 Vue.set(object, key, value) 将响应属性添加到嵌套的对象上:
Vue.set(vm.someObject, 'b', 2)
vm.$set
实例方法
this.$set(this.someObject,'b',2)
- vue全局set方法 Vue.set(object, key, value) 将响应属性添加到嵌套的对象上:
- 若想向已有对象上添加一些属性,例如使用
Object.assign()
或_.extend()
方法来添加属性。但是,添加到对象上的新属性不会触发更新。
但可以创建一个新的对象,让它包含原对象的属性和新的属性:123//代替 Object.assign(this.someObject, { a: 1, b: 2 })this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
- 若某属性没有在data对象上声明,不能使用
异步更新队列
Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。1234567891011121314151617Vue.component('example', {template: '<span>{{ message }}</span>',data: function () {return {message: '没有更新'}},methods: {updateMessage: function () {this.message = '更新完成'console.log(this.$el.textContent) // => '没有更新'this.$nextTick(function () {console.log(this.$el.textContent) // => '更新完成'})}}})
v-model
才是用来数据的双向绑定的正主
一开始v-model
主要用以表单控件的数据的双向绑定
vue2.2.0新增,自定义组件也可以用v-model
|
|
是不是觉得很眼熟:) ?
参考链接
What is the difference between properties and attributes in HTML? -Stack Overflow
深入理解vue.js双向绑定的实现原理