请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于新版本computed实现的问题

在新版本computed的实现,跟视频里的实现方式不一样了,有两个地方不是很清楚:
新版本watcher里,

  • depend方法是循环this.deps数组,然后每一项都执行this.deps[i].depend()方法,这个deps里的dep是什么时候加进去的
    图片描述

  • update方法只是把this.dirty赋值为true,是怎么触发所收集的watcher的重新渲染或者重新计算的
    图片描述

正在回答

1回答

ustbhuangyi 2019-07-02 14:00:37

首先计算属性是一个 computed watcher(lazy watcher)当我们首次 render 的时候会访问这个计算属性从而触发它的 getter进而执行下面逻辑。

//img1.sycdn.imooc.com//szimg/5d1ae7d400010fdb17860752.jpg

这里有 2 个步骤由于 computed  watcher dirty 为 true首先执行 watcher.evaluate 去求值。
//img1.sycdn.imooc.com//szimg/5d1ae8360001afdd07300278.jpg
执行 this.get()同时把 dirty 设置为 false再看一下 get 方法
//img1.sycdn.imooc.com//szimg/5d1ae86d00013eb717081244.jpg
注意每次 get 都会先 pushTarget所以现在 Dep.targert 是当前这个 computed Watcher。
然后它会执行 this.getter.call(vm, vm)这里就相当于调用了计算属性函数做求值由于我们知道计算属性往往依赖了 data、props 甚至是其它计算属性的数据所以这个时候会触发这些依赖的 getter会把这些依赖收集到当前这个 computed Watcher 中。在这个收集过程中会触发 Dep 中的 depend 方法
//img1.sycdn.imooc.com//szimg/5d1ae98800012e2907320300.jpg
其实就是执行 computed watcher 中的 addDep 方法
//img1.sycdn.imooc.com//szimg/5d1ae9af0001dab909300498.jpg
新的依赖会添加到 newDeps 中。
再回到 get 方法执行完t his.getter.call(vm, vm) 后会执行 popTagert这个时候 Dep.target 又回到了 render watcher 了接着又执行 cleanupDeps
//img1.sycdn.imooc.com//szimg/5d1aea350001ce3611100842.jpg
这个过程中会把新收集的依赖更新到 this.deps 中所以我们刚刚说的 computed watcher 的 deps 就是在执行计算属性函数求值过程中的依赖。

至此计算属性的求值完成依赖收集过程完成。接下来看第二个步骤
//img1.sycdn.imooc.com//szimg/5d1af16900016e8c05960148.jpg

把计算属性中的依赖收集到当前渲染 watcher 中。那么为啥要执行这个步骤我们要想一个问题假设我们的模板渲染过程中只访问了计算属性值触发了计算属性的的 Getter 执行了我们上述一系列操作那么当计算属性的依赖发生变化也只会触发 computed watcher 的 update
//img1.sycdn.imooc.com//szimg/5d1af2170001e90208060482.jpg
也仅仅是把 this.dirty 设置为 false并不会触发计算属性的重新计算也不会让页面重新渲染。所以我们需要把计算属性中的依赖收集到当前渲染 watcher 中。这样一旦计算属性的依赖发生变化就会触发 render watcher 的 update就会触发重新渲染在重新渲染的过程中会再次访问到计算属性的 getter。然后又回到最初
//img1.sycdn.imooc.com//szimg/5d1af2a9000149c518480682.jpg
因为计算属性的依赖更新触发了 computed watcher 的 update,dirty 为 true所以又触发了计算属性的重新计算。
这就是为什么当计算属性的依赖不改变计算属性就会用缓存的值只有它依赖发生了变化它才会重新计算。

6 回复 有任何疑惑可以回复我~
  • 提问者 SA9 #1
    非常感谢!
    回复 有任何疑惑可以回复我~ 2019-07-02 21:49:46
  • 也仅仅是把 this.dirty 设置为 false并不会触发计算属性的重新计算也不会让页面重新渲染   这是是不是设置成true啊?
    回复 有任何疑惑可以回复我~ 2021-04-12 18:59:01
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信