数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。
- How Changes are Tracked
- check change notice
- delcaring Reactive Properties
- async update Queue
如何追踪变化
当把普通的JavaScript对象传递给Vue实例的data选项, Vue遍历这个对象的属性:
使用Object.defineProperty()把属性{attr_name: value}格式转化为 getter/setter对儿。
个人理解:
ruby中的方法,attr_write 和attr_read和getter/setter类似都是操作对象读/写的方法。
普通JS对象内部的数据,每个数据(hash格式)被分配了getter/setter方法,用于进行读和写
getter/setter用于追踪依赖, 在属性被访问和修改时通知变化。
每个组件实例都有相应的watcher实例对象, 它会在组件渲染的过程中把属性记录为依赖dependency.
之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。
Object.defineProperty(obj, prop, descriptor)
这个方法直接在一个对象上定义一个新的属性,或修改现有的属性,返回这个对象。
- obj即对象
- prop 对象属性的名字或符号Symbol, 用于被定义或修改
- descriptor 被定义/修改的属性的描述
属性desciptor在对象中有2种主要形式:
- 数据描述符: attr-name: value。writable: true/false (正常的新增属性和修改属性值)
- 存取描述符号: 由一个getter/setter对儿函数来描述一个属性。用get, set方法来读/写属性值
属性描述符号只能二选一。它们都是对象。
get:一个函数,作为一个getter为属性服务。当属性被访问时,getter被调用。 this设置给对象
set:一个函数, 作为一个setter为属性服务。当属性被分配时,setter和一个参数value被调用, 参数分配给属性。 this设置给属性被分配的对象。
例子:
var o = {a: 37}; // 创建一个新对象
// 在对象中添加一个属性与存取描述符的示例
var bValue;
Object.defineProperty(o, "b", {
get : function(){
return bValue;
},
set : function(newValue){
bValue = newValue;
},
enumerable : true, #可以改变该描述符
configurable : true #该属性可以出现在对象的枚举属性中
});
o.b = 38;
// 对象o拥有了属性b,值为38
// o.b的值现在总是与bValue相同,除非重新定义o.b
检查变化的注意事项
Vue在初始化实例时对属性执行getter/setter转化过程。
之后给实例添加的属性是非react的,因为没有getter/setter方法。也就没办法监听watcher。
如果想要响应的属性,必须使用vm.$set(target, key, value)方法。新增属性到嵌套对象上。
猜测这个方法又调用了Object.defineProperty()。
声明响应属性
Vue不可以动态添加根级别的相应属性。所以在初始化实例前需要声明一个根级别的相应属性。可以是空值。
var vm = new Vue({
data: {
// 声明 message 为一个空值字符串
message: ''
},
template: '<div>{{ message }}</div>'
})
// 之后设置 `message`
vm.message = 'Hello!'
异步更新队列
(未理解)
猜测: