Vue Computed 浅析

https://zhuanlan.zhihu.com/p/62732142 理解 Vue computed ,网上搜了一堆文章,都是一开始扔一堆概念,不好理解,这里整理一下。
这篇文章应该倒着看,首先需要理解 Vue 的依赖收集阶段干了啥,包括如何收集 watch

先假设以下代码

1
2
3
4
5
6
7
8
9
10
11
12
<div>{{ b }}</div>

data() {
return {
a: 1,
}
},
computed: {
b() {
return this.a++
}
},

主要问题在于 computed : 为什么改变 a 时,b 会自动计算? a 与 b 如何建立的联系?

依赖收集

  1. 页面更新,收集 computed。

  2. Dep.target 设置为 页面 watcher。

    • Dep.target: 类似一个状态,表示当前谁在收集,这里设置为 页面 watcher
    • 页面 watcher: 表示页面收集状态为 收集全局变量状态
  3. computed 被读取,createComputedGetter 包装的函数触发,第一次进行计算

  4. 调用 computed-watcher.evaluted,接着调用 computed-watcher.get ,Dep.target 被设置为 computed-watcher,旧值 页面 watcher 被缓存起来。

    • computed 读取是一连串函数调用,读取时触发 data.get,进而拿到依赖的数据
    • Dep.target 设置为 computed收集 状态
    • 旧值 是页面收集全局变量时的值
  5. computed 会读取 data,此时 data 就收集到 computed-watcher

    • if (Dep.target === computed-watcher) computed依赖.push(data.value)
  6. computed-watcher 保存到 全局收集器列表: dep里

    • 在 createComputedGetter 获取到对应的 watcher
    • 对应的 watcher 就是文章开头时的 每个 computed 配发 watcher: 1、保存 computed 计算函数 2、保存计算结果 3、控制缓存计算结果是否有效
  7. computed 计算完成,Dep.target 恢复为 页面watcher

    • 全局收集恢复到 收集computed 前的状态
  8. watcher.depend,让 全局收集 收集到 computed-watcher.dep 里的数据

    • 于是 全局收集 里就有 computed 的 watch 数据了

整个依赖收集是同步执行的
设置 Dep.target 状态 ->
收集 computed ->
读取 data.value ->
触发 data.value.geter ->
加入到 computed.dep列表

缓存控制

依赖收集结束

  • a 更新时通知 知道自己被 computed.b 收集了,于是将 computed.b 的 dirty 设置为 true 表示需要更新b的数据
  • 之后通知 computed.b 让他更新数据