Vue2依赖收集原理
观察者模式定义了对象间一对多的依赖关系。即被观察者状态发生变动时,所有依赖于它的观察者都会得到通知并自动更新。解决了主体对象和观察者之间功能的耦合。
Vue中基于 Observer、Dep、Watcher 三个类实现了观察者模式
- Observer类 负责数据劫持,访问数据时,调用
dep.depend()
进行依赖收集;数据变更时,调用dep.notify()
通知观察者更新视图。我们的数据就是被观察者 - Dep类 负责收集观察者 watcher,以及通知观察者 watcher 进行 update 更新操作
- Watcher类 为观察者,负责订阅 dep,并在订阅时让 dep 同步收集当前 watcher。当接收到 dep 的通知时,执行 update 重新渲染视图
dep 和 watcher 是一个多对多的关系。每个组件都对应一个渲染 watcher,每个响应式属性都有一个 dep 收集器。一个组件可以包含多个属性(一个 watcher 对应多个 dep),一个属性可以被多个组件使用(一个 dep 对应多个 watcher)
Dep
我们需要给每个属性都增加一个 dep 收集器,目的就是收集 watcher。当响应式数据发生变化时,更新收集的所有 watcher
- 定义 subs 数组,当劫持到数据访问时,执行
dep.depend()
,通知 watcher 订阅 dep,然后在 watcher内部执行dep.addSub()
,通知 dep 收集 watcher - 当劫持到数据变更时,执行
dep.notify()
,通知所有的观察者 watcher 进行 update 更新操作
Dep有一个静态属性 target,全局唯*一,Dep.target 是当前正在执行的 watcher 实例,这是一个非常巧妙的设计!因为在同一时间只能有一个全局的 watcher
注意:
渲染/更新完毕后我们会立即清空 Dep.target,保证了只有在模版渲染/更新阶段的取值操作才会进行依赖收集。之后我们手动进行数据访问时,不会触发依赖收集,因为此时 Dep.target 已经重置为 null
相关文章