目录
计算属性的基本概念
计算属性的核心实现
ComputedRefImpl 类的实现
ReactiveEffect 与计算属性的关系
计算属性的工作流程
1. 创建计算属性
2. 依赖收集过程
3. 嵌套 effect 的处理
4. 更新过程
嵌套 effect 关系图解
依赖关系建立过程
代码实现分析
1. 创建计算属性
2. 访问计算属性
3. 响应式数据变化时
具体流程示例
关键点总结
计算属性的缓存机制
总结
计算属性是 Vue 中非常重要的特性,它允许我们声明性地计算衍生值。本文将深入探讨 Vue 的计算属性是如何实现的,特别是它如何依赖 ReactiveEffect
来完成响应式更新。
计算属性的基本概念
计算属性本质上是一个可缓存的值,它只有在依赖的响应式数据发生变化时才会重新计算。这种特性使得计算属性非常适合处理复杂的逻辑计算。
计算属性的核心实现
export function computed(getterOrOptions) {let getter;let setter;let onlyGetter = isFunction(getterOrOptions);if (onlyGetter) {getter = getterOrOptions;setter = () => {};} else {getter = getterOrOptions.get;setter = getterOrOptions.set;}return new ComputedRefImpl(getter, setter);
}
computed
函数接收一个 getter 函数或者一个包含 get 和 set 方法的对象,然后返回一个
ComputedRefImpl
实例。这个实例就是我们使用的计算属性。
ComputedRefImpl 类的实现
class ComputedRefImpl {public _value;public effect;public dep;constructor(public getter, public setter) {this.effect = new ReactiveEffect(() => getter(this._value),() => {triggerRefValue(this);});}get value() {if (this.effect.dirty) {this._value = this.effect.run();trackRefValue(this);}return this._value;}set value(newValue) {this.setter(newValue);}
}
ComputedRefImpl
类是计算属性的核心实现,它包含了三个关键属性:
-
_value
:存储计算结果 -
effect
:一个ReactiveEffect
实例,用于追踪依赖和触发更新 -
dep
:存储依赖于这个计算属性的其他 effect
ReactiveEffect 与计算属性的关系
计算属性的实现依赖于 ReactiveEffect
类。让我们看看 ReactiveEffect
的关键部分:
export class ReactiveEffect {_trackId = 0;deps = [];_depsLength = 0;_runing = 0;_dirtyLevel = DirtyLevel.Dirty;public active = true;constructor(public fn, public scheduler) {}public get dirty() {return this._dirtyLevel === DirtyLevel.Dirty;}public set dirty(value) {this._dirtyLevel = value ?