vue2 响应式原理(一)
简要介绍
vue2响应式主要通过 object.defineProperty 对响应式对象的每个属性进行监听 在get时收集依赖,在set设置属性值时触发所有依赖更新
下面带大家实现一下简单的响应式,主要下述几个关键类和函数:
- observe(obj) 负责将 obj 设为响应式对象
- defineReactive(obj, key) 将obj的每个属性进行劫持,get时收集依赖,set时触发更新
- Dep类 保存对象单项属性的依赖
- Watcher类 依赖本身
observe的实现
js
function observe(obj) {
// 判断下obj为对象且不为null,不然直接返回
if(typeof obj !== 'object' || obj == null) return obj;
// 遍历每个属性都设置为响应式
Object.keys(obj).forEach((key) => {
defineReactive(obj, key);
})
}
defineReactive 的实现
js
function defineReactive(obj, key) {
// 递归深层遍历属性设置响应式
if(typeof obj[key] !== 'object' || obj[key] == null) observe(obj[key]);
// Dep类的作用是,收集保存每个属性的依赖
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
// 收集依赖,后面详细解释Dep.target的作用
Dep.target && dep.addSub(Dep.target)
return obj[key];
},
set(newValue) {
// dep.subs保存的所有依赖,每个sub都是一个Watcher对象
if(newValue !== obj[key]) dep.notify();
}
})
}
Dep类的实现
js
Class Dep {
constructor() {
// 存放依赖列表
this.subs = [];
}
addSub(sub) {
this.subs.push(sub)
}
notify() {
this.subs.forEach(sub => sub.upload())
}
}
Watcher的实现
js
Class Watcher {
constructor(obj, key, callBack) {
this.obj = obj;
this.callBack = callBack;
Dep.target = this;
// 触发get收集依赖
this.value = obj[key];
Dep.target = null;
}
upload() {
if(this.value !== this.obj[key]) {
this.value = this.obj[key];
this.callBack();
}
}
}
大佬们如果有哪里漏掉了还请多多指点~