vue双向数据绑定实现的原理?
程序员文章站
2024-02-01 18:35:52
...
vue双向数据绑定实现的原理?
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。
当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
#####2.Object.defineProperty()
Object.defineProperty() 方法用于在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。注意:只能在Object 构造器对象上调用此方法,而不能在任意一个 Object 类型的实例上调用。
Object.defineProperty(obj, prop, descriptor)
参数
obj:目标对象,就是要在这个对象上面定义属性
prop:要定义或修改的属性的名称或 Symbol 。
descriptor:要定义或修改的属性描述符。是一个对象
通过赋值操作添加的普通属性是可枚举的,(for…in 或 Object.keys 方法),既可以改变这些属性的值,也可以删除这些属性。
Object.defineProperty()方法可以通过对属性的配置,实现更精确的控制
关于descriptor:对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。
数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。
存取描述符是由 getter 函数和 setter 函数所描述的属性。
一个描述符只能是这两者其中之一;不能同时是两者。
数据描述符和存取描述符都是对象。它们共享以下可选键值(默认值是指在使用 Object.defineProperty() 定义属性时的默认值):
configurable
是否可以删除目标属性:当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。(使用delete删除)
默认为 false。
enumerable
当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。
默认为 false。
数据描述符还具有以下可选键值:
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
默认为 undefined。
writable
该属性的值是否可以被重写:当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。
默认为 false。
示例:
存取描述符还具有以下可选键值
get 属性,是一个函数,是一种获得属性值的方法
如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
默认为 undefined。
set 属性,是一个函数,是一种设置属性值的方法
如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
默认为 undefined。
示例:
<script>
// 在对象中添加一个设置了存取描述符属性的示例
var bValue = 38;
Object.defineProperty(o, "b", {
// 使用了方法名称缩写(ES2015 特性)
// 下面两个缩写等价于:
// get : function() { return bValue; },
// set : function(newValue) { bValue = newValue; },
get() {
console.log('有人访问数据了');
return bValue;
},
set(newValue) {
console.log('设置了新值');
bValue = newValue;
},
enumerable: true,
configurable: true
});
o.b; // 38
// 对象 o 拥有了属性 b,值为 38
// 现在,除非重新定义 o.b,o.b 的值总是与 bValue 相同
// 数据描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", {
value: 0x9f91102,
get() { return 0xdeadbeef; }
});
// 抛出错误 TypeError: value appears only in data descriptors, get appears only in accessor descriptors
</script>
说明:
拥有布尔值的键 configurable、enumerable 和 writable 的默认值都是 false。
属性值和函数的键 value、get 和 set 字段的默认值为 undefined。
实现vue的双向数据绑定:
上一篇: PHP的Zlib跟gzhandle