知食记
搜索文档…
vue-computed原理

为什么computed可以缓存

vue2.0中,computed是基于watch的。
watch实现中函数
1
evaluate () {
2
this.value = this.get()
3
this.dirty = false
4
}
Copied!
computed 实现中的函数
1
//计算属性的getter 获取计算属性的值时会调用
2
createComputedGetter (key) {
3
return function computedGetter () {
4
//获取到相应的watcher
5
const watcher = this._computedWatchers && this._computedWatchers[key]
6
if (watcher) {
7
//watcher.dirty 参数决定了计算属性值是否需要重新计算,默认值为true,即第一次时会调用一次
8
if (watcher.dirty) {
9
/*每次执行之后watcher.dirty会设置为false,只要依赖的data值改变时才会触发
10
watcher.dirty为true,从而获取值时从新计算*/
11
watcher.evaluate()
12
}
13
//获取依赖
14
if (Dep.target) {
15
watcher.depend()
16
}
17
//返回计算属性的值
18
return watcher.value
19
}
20
}
21
}
Copied!
watch 中的update 函数
1
//更新
2
update () {
3
if (this.lazy) {
4
this.dirty = true
5
}else{
6
this.run()
7
}
Copied!
只有watch收集到更新了才会触发computed计算,否则直接返回缓存值

总结

computed 本质是一个惰性求值的观察者。
computed 内部实现了一个惰性的 watcher,也就是 computed watcher,computed watcher 不会立刻求值,同时持有一个 dep 实例。
其内部通过 this.dirty 属性标记计算属性是否需要重新求值。
当 computed 的依赖状态发生改变时,就会通知这个惰性的 watcher,
computed watcher 通过 this.dep.subs.length 判断有没有订阅者,
有的话,会重新计算,然后对比新旧值,如果变化了,会重新渲染。 (Vue 想确保不仅仅是计算属性依赖的值发生变化,而是当计算属性最终计算的值发生变化时才会触发渲染 watcher 重新渲染,本质上是一种优化。)
没有的话,仅仅把 this.dirty = true。 (当计算属性依赖于其他数据时,属性并不会立即重新计算,只有之后其他地方需要读取属性的时候,它才会真正计算,即具备 lazy(懒计算)特性。)
最近更新 1yr ago