收集依赖
来源:4-5 依赖收集(上)

前端工程师666777888
2021-03-28
收集依赖的过程:
1一定是先给属性设置get和set方法
2第二步:执行new Watcher()生成watcher
3第三步:生成watcher后,再执行属性的get方法。开始收集
注意:之所以把生成的watcher保存在一个全局变量(Dep.target)中,因为这个watcher可能被多个属性收集。这样我们就知道这多个属性实际收集的是同一个watcher
感觉计算属性的依赖收集比data属性和watch属性都要麻烦。而且框架对于计算属性的依赖收集单独做的处理也比较多
假设计算属性在模板中引用了
有一点不太明白:计算属性本身会有个render watcher吗?但是当计算属性变化时,确实会重新渲染组件,好像是执行了render watcher。这个render watcher是在什么时候收集的,是谁收集的?因为我感觉在模板中访问计算属性时,执行计算属性对应的get方法,这里面的watcher好像一直都是computed watcher。当computed watcher收集完后,才会暴露出render watcher。 ????
对于targetStack这个全局变量。
我的理解如下:
1.user watcher生成后,会把user watcher放到targetStack数组中,当执行完依赖收集,会清空targetStack。此时targetStack又为空数组
2.在执行$mount过程中,当前watcher一直是render watcher。targetStack中会放入这个render watcher。
3如果模板中引用了计算属性,计算属性的方法中又引用了data中的属性,在render watcher下面(记住:此时的render watcher还没结束。一个watcher结束的标识:当watcher.get()方法执行完毕。),又会生成一个computed watcher,此时当前活跃的watcher又变成了computed watcher,targetStack中又会存入这个computed watcher。现在targetStack中有2个watcher了。记住:render watcher是外层的watcher,而computed watcher是内层的watcher,一定是内层的watcher先执行结束。当computed watcher结束时,targetStack会把computed watcher删除,此时当前活跃的watcher又为render watcher了。大致是这样一种情况
注:computed watcher在初始化时就生成了。先把生成的watcher保存在watchers[属性名]中了。此时仅仅生成了watcher,并没有收集依赖。当计算属性在模板中引用时,才会触发依赖收集
注:
1、user watcher是独立的,不存在watcher中嵌套watcher
2、render watcher和computed watcher一定是混在一起的,所以才有Dep.target和targetStack这两个全局变量,为的是把里面的watcher给明确化:让我们知道现在用的是哪个watcher,接下来又该用哪个watcher了
set的过程就好理解了
改变一个值,执行之前它收集好的依赖就行了
render watcher最后执行的是渲染组件
computed watcher最后执行的是我们写的那个函数
user watcher最后执行的也是我们写的那个函数
1回答
-
computed watcher 和 render watcher 是独立的两个 watcher,你是因为在模板中访问了计算属性,才会有嵌套关系。
这种嵌套关系很好构造,比如一个计算属性依赖另一个计算属性,或者你手动 watch 一个计算属性的变化,都会形成这种嵌套关系,所以 targetStack 才设计成这样的栈的数据结构,还是很巧妙的,建议你多写几个 demo 调试。10
相似问题