```javascript
```javascript
当创建Vue实例时,vue会遍历data选项的属性,利用Object.defineProperty为
属性添加getter和setter对数据的读取进行劫持(getter用来依赖收集,setter用来派发更新)
,并且在内部追踪依赖,在属性被访问和修改时通知变化。
每个组件实例会有相应的watcher实例,会在组件渲染的过程中记录依赖的所有数据属性
(进行依赖收集,还有computed watcher,user watcher实例),之后依赖项被改动时,
setter方法会通知依赖与此data的watcher实例重新计算(派发更新),
从而使它关联的组件重新渲染。
function observe(target) {
// 若target是一个对象,则遍历它
if (target && typeof target === “Object”) {
Object.keys(target).forEach((key) => {
// defineReactive方法会给目标属性装上“监听器”
defineReactive(target, key, target[key]);
});
}
}
// 定义defineReactive方法
function defineReactive(target, key, val) {
const dep = new Dep();
// 属性值也可能是object类型,这种情况下需要调用observe进行递归遍历
observe(val);
// 为当前属性安装监听器
Object.defineProperty(target, key, {
// 可枚举
enumerable: true,
// 不可配置
configurable: false,
get: function () {
return val;
},
// 监听器函数
set: function (value) {
dep.notify();
},
});
}
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach((sub) => {
sub.update();
});
}
}