Computed原理

讲一下computed的原理:

 

简单总结:在initComputed的时候,会将computed对象中的每一个key创建一个watcher,watcher的getter就是你写的函数,当依赖变化的时候,这个watcher 会将自己的lazy属性设置为true。 并不计算自己的值,  然后将computed的key通过设置defineProperty getter setter设置到vm上,(defineComputed方法),

同时,让组件的渲染watcher也收集依赖,当依赖变化的时候,触发渲染watcher的更新方法, 会判断computed watcher是否为dirty,如果为dirty,那么计算,拿到值,然后dirty设为false,否则直接拿值。

 

 

 

答: 

 

在initState方法中有一个initComputed方法,

 

会对computed对象中的key和value(value是一个函数)进行处理

 

1.首先为computed对象的每一个key,对应value创建实例化一个watcher(使用这个value函数,当做new watcher的第二个参数),

computedWatcherOptions传入了lazy属性为true,以此,每个watcher内部的dirty属性=lazy=true

  (创建了watcher会怎么样呢? 当function内数据发生变化的时候,会通知watcher,执行watcher的update函数,又因为在.prototype.update方法中会判断 if(this.lazy){this.dirty = true},所以 如果函数中的数据发生了改变,watcher的dirty属性会变成true,!注意并不会计算,只是把dirty属性变为true了)

 

2.接下来,如果vm上没有这个key的话,将执行defineComputed将这个computed key设置到vm上,使用是的Object.defineProperty,

  设置到vm上,其中,getter是使用createComputedGetter(key)返回的     <-----其实这个get就是拿这个watcher的value,如果dirty还需要先计算再拿

 

   这个createComputedGetter

   返回一个新的函数作为getter

 

 

 

 1.watcher有一个dirty属性和evaluate方法,如果dirty是true的话,会执行evaluate方法得到最新的数据,(evaluate函数中之后dirty设置为false)

   否则,将直接返回旧的数据(watcher实例的value属性

 

    

 2.使用Dep.target建立vm组件渲染watcher和计算属性中状态的依赖关系,即:

     (此时Dep.target是vm组件渲染watcher 具体见)

    

那么执行watcher.depend() ,这里的watcher是计算属性的某一个watcher,depend方法会遍历和watcher自身关联的所有dep(即,这个计算属性中用到的所有状态),并与Dep.target建立关系(,此时Dep.target是vm组件渲染watcher),

 

建立了关系之后,当计算属性依赖的一个状态发生变化时,

会: 1.通知计算属性的watcher,数据发生了变化,(进而执行update方法)将计算属性的dirty属性设置为true

2.通知组件渲染watcher,数据发生了变化,需要重新渲染,渲染时候,会拿watcher的value,如果计算属性getter对应的watcher的 dirty属性为true 引发计算新值。

 

  

 

关于计算属性的”缓存“:

为什么说计算属性有缓存功能呢,

假设一个template中

 {{ computedVal }} // computedVal定义在计算属性中,是a+b

另一个是

 {{ a+b }}

语法中是一个计算属性,那么每次render的时候都会计算a+b,而computedVal不会计算,如果值没变化,依赖的dirty依然保持false,渲染时也是直接拿value(对应的一个watcher的value)

posted @ 2020-05-10 14:05  hh9515  阅读(1277)  评论(0)    收藏  举报