其实这里挺好理解的,首先什么情况下childOb
会不为空呢?当val
是对象或者是数组的时候,也就是说,当**val**
是对象或者数组的情况下,触发get函数(也就是说读取该值)的时候,依赖会被添加到两个dep实例里面:
- 一个是
**defineReactive**
函数构建的闭包中的**dep**
。 - 另一个是这个对象或者数组对应的observer实例的
**dep**
属性。为什么Vue要将依赖进行两处的添加呢?
有时候会觉得很奇怪为什么要将依赖添加到两个不同的地方。其实他们都有自己的用途。我举个例子:let data = {
obj: {}
}
当我们进行对
**data.obj**
进行赋值操作的时候,针对这个属性的依赖或者说观察者是不是应该进行**update**
呢?这是当然的。所以这个时候,**Vue**
在**set**
函数中就使用**defineReactive**
中的**dep**
进行**notify**
操作。 当我们对这个**obj**
对象进行属性删除(**$delete**
)、属性添加(**$set**
)的时候,针对 这个属性的观察者是不是应该更新,这是理所当然的。但是由于上述行为无法触发**set**
函数,所以导致观察者无法触发**update**
。这个时候挂载在**observer**
实例身上的**dep**
实例就发挥作用了。我们可以**obj.__ob__.dep.notify()**
这样来触发针对**obj**
属性的那些观察者更新。 同样的,数组是一样的道理,**push**
等操作都是无法触发**set**
函数的,所以也是通过第二个**dep**
实例来触发观察者们的更新。