概述
- 本文是解析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, //
};
// 创建Dep类
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());
}
}
// 创建Watcher类
class Wacher {
run() { // 要执行更新的主体
console.log("更新内容");
}
addDep(dep) {
// 这里的this表示当前的Watcher实例
dep.addSub(this);
}
}
// 收集某个key 的依赖——页面上哪些地方用到了
const dep = new DepClass();
dep.target = new Wacher();
Object.defineProperty(proxyObj, "num", {
get() {
dep.depend(); // 获取一次“num”值,Dep就添加一次依赖
return originObj.num;
},
set(newValue) {
dep.notify(); // 重新赋值一次,就通知订阅者重新更新(添加的Watcher重新计算)
return (originObj.num = newValue);
},
});
// 调试代码
console.log(proxyObj.num); // 模拟页面中哪些地方用到了代理的Key
proxyObj.num = 39; // 重新复制后,dep通知订阅者们重新执行
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END