最近在看vue源码的时候遇到一个问题
在创建Observer
时会给observer
实例创建一个依赖Dep
export class Observer {
value: any;
dep: Dep; // <---------这里
vmCount: number; // number of vms that has this object as root $data
constructor (value: any) {
this.value = value
this.dep = new Dep()
this.vmCount = 0
def(value, '__ob__', this)
if (Array.isArray(value)) {
const augment = hasProto
? protoAugment
: copyAugment
augment(value, arrayMethods, arrayKeys)
this.observeArray(value)
} else {
this.walk(value)
}
}
}
将对象的每个属性转换为setter
和getter
的时候,又new了一个Dep
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: ?Function,
shallow?: boolean
) {
let childOb = !shallow && observe(val) // 如果是对象 创建自Observer
const dep = new Dep() // #1 <---
Object.defineProperty(obj,key,{
//省略部分
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()// 这里用的是 #1
if (childOb) {
childOb.dep.depend() //这里用的是子Observer实例的dep属性 #2
}
if (Array.isArray(value)) {
dependArray(value)
}
}
return value
}
}
)
我的问题是:#1
和#2
这两个Dep
有什么区别?如果属性是个对象的话,这里是不是重复的依赖?
你在Vue代码中全局搜一下dep.notify就差不多明白了。
一共有四个地方调用了dep.notify。
其中三个地方是调用了ob.dep.notify()。
分别是:
1.对数组push等七个方法重写的函数中
2.set方法,为一个对象添加一个属性
3.del方法,为对象删除一个属性
而闭包中的dep.notify()只是在Object.defineProperty的set方法中触发。
那么很清楚了,#1是闭包中的Dep,用于由对象本身修改而触发setter函数导致闭包中的Dep通知所有的Watcher对象。#2则是在对象本身增删属性或者数组变化的时候被触发的Dep。