概述
- 本文是解析Vue的响应式原理。在Vue2.0中,数据的代理是用使用
Object.difineProperty实现,但这只是响应式原理的部分。在源码中,还涉及到Dep、Watcher这两个类,负责收集依赖、创建订观察者。
- Dep的功能是收集依赖,具体指某个变量在哪些地方用到了,如HTML页面、computed、watch中。当这个变量变化后,使用到这个变量的所有地方都会重新更新。
- Watcher:观察者,表示使用到某个变量的地方,有地方用到了就创建观察者。当某个变量重新赋值后,触发Dep通知更新时,该变量的观察者们全部重新执行,之后再通过渲染更新到页面中。
Dep类简介
- 该类有提供
depend方法(表示添加订阅者)、notify方法(通知订阅者们更新)、subs属性(表示订阅者)
- subs是一个数组,里面存放Watcher实例,表示哪些地方用到了指定的代理数据
- 有兴趣的同学可以看源码
dep.js
Watcher简介
- 该类有提供addDep(添加到Dep中,收集依赖)
- 有兴趣的同学可以看源码
watcher.js
调试代码实现——模拟整个流程
- 构造
DepClass、Wacher类
- 代理数据,下面代码中代理
“num”数据举例
- 模拟页面使用
num的场景(比如实际开发中展示num属性值),出发Dep类收集依赖(depend方法)。
- 给
num重新赋值,触发Dep通知订阅者(subs属性)更新
- 流程图示

const proxyObj = {};
const originObj = {
num: 20,
};
class DepClass {
subs = [];
target = null;
addSub(sub) {
this.subs.push(sub);
console.log("--sss", this.subs);
}
depend() {
console.log("dep类收集依赖---");
if (this.target) {
this.target.addDep(this);
}
}
notify() {
console.log("执行notify -> 通知订阅们 -> 重新执行", this.subs);
this.subs.forEach((sub) => sub.run());
}
}
class Wacher {
run() {
console.log("更新内容");
}
addDep(dep) {
dep.addSub(this);
}
}
const dep = new DepClass();
dep.target = new Wacher();
Object.defineProperty(proxyObj, "num", {
get() {
dep.depend();
return originObj.num;
},
set(newValue) {
dep.notify();
return (originObj.num = newValue);
},
});
console.log(proxyObj.num);
proxyObj.num = 39;