为什么computed可以缓存
vue2.0中,computed是基于watch的。
evaluate () {
this.value = this.get()
this.dirty = false
}
//计算属性的getter 获取计算属性的值时会调用
createComputedGetter (key) {
return function computedGetter () {
//获取到相应的watcher
const watcher = this._computedWatchers && this._computedWatchers[key]
if (watcher) {
//watcher.dirty 参数决定了计算属性值是否需要重新计算,默认值为true,即第一次时会调用一次
if (watcher.dirty) {
/*每次执行之后watcher.dirty会设置为false,只要依赖的data值改变时才会触发
watcher.dirty为true,从而获取值时从新计算*/
watcher.evaluate()
}
//获取依赖
if (Dep.target) {
watcher.depend()
}
//返回计算属性的值
return watcher.value
}
}
}
//更新
update () {
if (this.lazy) {
this.dirty = true
}else{
this.run()
}
只有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(懒计算)特性。)