computed的初始化过程,会遍历computed的每一个属性值,并为每一个属性实例化一个computed watcher,其中{ lazy: true}computed watcher的标志,最终会调用defineComputed将数据设置为响应式数据,对应源码如下:

    defineComputed的逻辑和分析data的逻辑相似,最终调用Object.defineProperty进行数据拦截。具体的定义如下:

    在非服务端渲染的情形,计算属性的计算结果会被缓存,缓存的意义在于,只有在相关响应式数据发生变化时,computed才会重新求值,其余情况多次访问计算属性的值都会返回之前计算的结果,这就是缓存的优化computed属性有两种写法,一种是函数,另一种是对象,其中对象的写法需要提供gettersetter方法。

    createComputedGetter返回的函数在执行过程中会先拿到属性的computed watcher,dirty是标志是否已经执行过计算结果,如果执行过则不会执行watcher.evaluate重复计算,这也是缓存的原理。

    get方法前面介绍过,会调用实例化时传递的执行函数,在computer watcher的场景下,执行函数是计算属性的计算函数,他可以是一个函数,也可以是对象的getter方法。

    这就是computed依赖收集的完整过程,对比data的依赖收集,computed会对运算的结果进行缓存,避免重复执行运算过程。

    7.10.2 派发更新

    派发更新的条件是data中数据发生改变,所以大部分的逻辑和分析data时一致,我们做一个总结。

    • 当计算属性依赖的数据发生更新时,由于数据的Dep收集过computed watch这个依赖,所以会调用depnotify方法,对依赖进行状态更新。

    由于lazy属性的存在,update过程不会执行状态更新的操作,只会将dirty标记为true

    • 由于data数据拥有渲染watcher这个依赖,所以同时会执行updateComponent进行视图重新渲染,而render过程中会访问到计算属性,此时由于值为true,又会对计算属性重新求值。