前言
之前学习vue时看过部分源码,当时只是大概了解了一下vue响应式原理,还有diff算法和VNode那块,
最近稍微有点空,正好回过头来再细细过下。
正文
看过vue源码的各位大佬从标题应该就能看出来这篇内容水什么,/手动狗头/....。
首先我们知道Dep类的作用就是存放依赖,它负责收集依赖,并且当数据发值发生变化后通知Watcher更新,
so 我们每一个响应式的值都需要一个Dep实例,/无图言diao/...。我就贴下这块相关代码。
export default function defineReactive(data, key, val) {
//闭包保存的Dep类
const dep = new Dep();
console.log(dep,key)
if (arguments.length == 2) {
val = data[key];
}
// 子元素要进行 observe, 至此形成了递归,
// 这个递归不是函数自己调用自己
let childOb = observe(val); //Observer对象保存下来
Object.defineProperty(data, key, {
// 可枚举
emuerable: true,
// 可以被配置,比如可以被 delete
configurable: true,
get() {
console.log(`正在访问${key}属性`, val);
// 如果现在处于依赖收集阶段
if (Dep.target) {
dep.depend();
if (childOb) {
childOb.dep.depend(); //利用childOb对象上的dep去收集一次依赖
}
}
return val;
},
set(newValue) {
console.log(`正在改变${key}属性`, newValue);
if (val === newValue) { return };
val = newValue;
// 当设置了新值,新值也要 observe
childOb = observe(newValue);
// 发布订阅模式
dep.notify();
}
})
}
//Observer类
class Observer {
constructor(value) {
this.dep = new Dep()
def(value, '__ob__', this, false)
if (Array.isArray(value)) {
// ...
} else {
// ...
}
}
// ...
}
再每次执行defineReactive方法将一个键值变成响应式时,都会利用闭包保存它的dep,也就是上面的
const dep = new Dep()然后在下面触发get的时候进行依赖收集。这时候有人可能已经发现了,Observer类构造器中也会实例化一个dep对象来保存依赖,那它两都起作用还是???
继续看defineReactive,我们可以看到拿到当前key对应的值后对他进行响应式处理,并将返回的observer对象赋给了childOb,可以看出在触发依赖收集的时候,不光对当前入参的key的依赖列表进行收集,还对对应值的依赖列表进行收集;那这与childOb对象上的dep.append在收集一次有什么关系呢?
讲到这里我举个栗子吧
gg