官网
https://v2.cn.vuejs.org/v2/guide/reactivity.html
说明
vue双向数据绑定是 通过 数据劫持 并结合 发布-订阅模式 的方法来实现的。
其核心就是通过Object.defineProperty()方法设置set和get函数来实现数据的劫持,在数据变化时发布消息给订阅者,触发相应的监听回调来更新视图。
也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变
解释
1、数据劫持
(1)Object.defineProperty()方法
- MSN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
- 作用:会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
- 语法:
Object.defineProperty(obj, prop, descriptor)
// obj: 要定义属性的对象
// prop: 要定义或修改的属性的名称或 Symbol
// descriptor: 要定义或修改的属性描述符
- 示例:
var o = {}; // 创建一个新对象
// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
value : 37, // 属性值
writable : true, // 控制属性是否可以被修改,默认值是false
enumerable : true, // 控制属性是否可以枚举,默认值是false
configurable : true // 控制属性是否可以被删除,默认值是false
});
// 对象 o 拥有了属性 a,值为 37
// 在对象中添加一个设置了存取描述符属性的示例
var bValue = 38;
Object.defineProperty(o, "b", {
// 使用了方法名称缩写(ES2015 特性)
// 下面两个缩写等价于:
// get : function() { return bValue; },
// set : function(newValue) { bValue = newValue; },
get() { return bValue; }, // 获取值的时候会被调用,默认值是undefined
set(newValue) { bValue = newValue; }, // 设置值的时候会被调用,默认值是undefined
enumerable : true,
configurable : true
});
o.b; // 38
// 对象 o 拥有了属性 b,值为 38
// 现在,除非重新定义 o.b,o.b 的值总是与 bValue 相同
// 数据描述符和存取描述符不能混合使用
// 当使用了getter或setter方法,不允许使用writable和value这两个属性
Object.defineProperty(o, "conflict", {
value: 0x9f91102,
get() { return 0xdeadbeef; }
});
// 抛出错误
- 注意:get或set不是必须成对出现,任写其一就可以。
(2)实现
Vue 通过 Object.defineProperty() 方法遍历定义在 data 中的属性的所有 property ,把这些 property 全部转为 getter/setter。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter(发布者发布数据) 触发时,会通知 watcher (消息中心Broker),从而使它关联的组件重新渲染。
2、发布-订阅者模式
https://blog.csdn.net/weixin_43842373/article/details/121975015?spm=1001.2014.3001.5501