Vue数据绑定简析小结(8)

根据情况对数据进行遍历添加 __ob__ ,将 Dep.target 收集到 childOb.dep 的观察者列表,以便在增加/删除数据时能通知到观察者

通过 dependArray 将数组型的 value 递归进行观察者收集,在数组元素发生增、删、改时能通知到观察者

target[key] 的 setter 主要作用是对新数据进行观察,并通过闭包保存到 childOb 变量供 getter 使用,同时调用 dep.notify 通知观察者,在此就不再展开。

Watcher

在前面的篇幅中,我们主要介绍了 defineReactive 来定义响应式数据:通过闭包保存 dep 和 childOb ,在 getter 时来进行观察者的收集,使得在数据修改时能触发 dep.notify 或 childOb.dep.notify 来调用观察者的方法进行更新。但具体是如何进行 watcher 收集的却未做过多解释,现在我们将通过阅读 Watcher 来了解观察者背后的逻辑。

function initComputed (vm: Component, computed: Object) {
 const watchers = vm._computedWatchers = Object.create(null)
 const isSSR = isServerRendering()

 for (const key in computed) {
  const userDef = computed[key]
  const getter = typeof userDef === 'function' ? userDef : userDef.get

  if (!isSSR) {
   // create internal watcher for the computed property.
   watchers[key] = new Watcher(
    vm,
    getter || noop,
    noop,
    computedWatcherOptions
   )
  }
  ...
 }
}

这是 Vue 计算属性的初始化操作,去掉了一部分不影响的代码。首先初始化对象 vm._computedWatchers 用以存储所有的计算属性, isSSR 用以判断是否为服务端渲染。再根据我们编写的 computed 键值对循环遍历,如果不是服务端渲染,则为每个计算属性实例化一个 Watcher ,并以键值对的形式保存到 vm._computedWatchers 对象,接下来我们主要看下 Watcher 这个类。

Watcher 的构造函数

构造函数接受5个参数,其中当前 Vue 实例 vm 、求值表达式 expOrFn (支持 Function 或者 String ,计算属性中一般为 Function ),回调函数 cb 这三个为必传参数。设置 this.vm = vm 用以后续绑定 this.getter 的执行环境,并将 this 推入 vm._watchers ( vm._watchers 用以维护实例 vm 中所有的观察者),另外根据是否为渲染观察者来赋值 vm._watcher = this (常用的 render 即为渲染观察者)。接着根据 options 进行一系列的初始化操作。其中有几个属性:

  • this.lazy:设置是否懒求值,这样能保证有多个被观察者发生变化时,能只调用求值一次。
  • this.dirty:配合this.lazy,用以标记当前观察者是否需要重新求值。
  • this.deps、this.newDeps、this.depIds、this.newDepIds:用以维护被观察对象的列表。
  • this.getter:求值函数。
  • this.value:求值函数返回的值,即为计算属性中的值。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/385.html