Vue2依赖收集原理

2023-04-04 00:00:00 数组 依赖 实例 收集 观察者

观察者模式定义了对象间一对多的依赖关系。即被观察者状态发生变动时,所有依赖于它的观察者都会得到通知并自动更新。解决了主体对象和观察者之间功能的耦合。

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

  1. 定义 subs 数组,当劫持到数据访问时,执行 dep.depend(),通知 watcher 订阅 dep,然后在 watcher内部执行dep.addSub(),通知 dep 收集 watcher
  2. 当劫持到数据变更时,执行dep.notify() ,通知所有的观察者 watcher 进行 update 更新操作

Dep有一个静态属性 target,全局唯*一,Dep.target 是当前正在执行的 watcher 实例,这是一个非常巧妙的设计!因为在同一时间只能有一个全局的 watcher

注意:
渲染/更新完毕后我们会立即清空 Dep.target,保证了只有在模版渲染/更新阶段的取值操作才会进行依赖收集。之后我们手动进行数据访问时,不会触发依赖收集,因为此时 Dep.target 已经重置为 null

javascript

相关文章