Vue3 的响应式系统源码级 computed 的实现原理与缓存机制
字数 677 2025-11-17 18:10:47
Vue3 的响应式系统源码级 computed 的实现原理与缓存机制
知识点描述
computed 属性是 Vue3 响应式系统的核心功能之一,它能够基于响应式数据自动计算并缓存结果。当依赖的响应式数据未变化时,computed 会直接返回缓存值而不重新计算,这种缓存机制对性能优化至关重要。
实现原理详解
1. computed 的基本结构
class ComputedRefImpl<T> {
private _value!: T
private _dirty = true // 缓存标识
public readonly effect: ReactiveEffect<T>
constructor(getter: ComputedGetter<T>) {
this.effect = new ReactiveEffect(getter, () => {
if (!this._dirty) {
this._dirty = true // 依赖变化时标记为脏值
trigger(this, TriggerOpTypes.SET, 'value')
}
})
}
get value() {
track(this, TrackOpTypes.GET, 'value')
if (this._dirty) {
this._value = this.effect.run()
this._dirty = false // 计算完成后标记为干净值
}
return this._value
}
}
2. 依赖收集与缓存标识
- 当首次访问 computed 的 value 时,会执行 getter 函数并建立依赖关系
_dirty标志位控制是否需要进行重新计算:true:需要重新计算(依赖数据已变化)false:直接返回缓存值
3. 响应式更新流程
// 示例代码演示更新过程
const count = ref(0)
const double = computed(() => count.value * 2)
// 首次访问:计算并缓存
console.log(double.value) // 输出 0
// 执行过程:
// 1. track(double, 'value') 建立依赖关系
// 2. _dirty=true → 执行effect.run() → 计算得0
// 3. 设置_dirty=false,缓存结果
// 依赖数据变化
count.value = 1
// 触发computed的scheduler:
// 1. 设置_dirty=true(标记需要重新计算)
// 2. trigger(double, 'set', 'value') 通知依赖方
// 再次访问:检测到_dirty=true,重新计算
console.log(double.value) // 输出 2
4. 懒计算机制
- computed 采用懒计算策略:只有在真正访问 value 时才执行计算
- 与 watchEffect 的立即执行形成对比,避免不必要的计算开销
5. 嵌套 computed 的处理
const a = ref(1)
const b = computed(() => a.value + 1)
const c = computed(() => b.value + 1)
// 依赖链:a → b → c
a.value = 2
// 更新流程:
// 1. a变化触发b的scheduler,标记b为dirty
// 2. b变化触发c的scheduler,标记c为dirty
// 3. 访问c.value时,逐级重新计算
6. 缓存失效策略
- 当 computed 的依赖项发生变化时,scheduler 会被触发
- scheduler 将
_dirty设为 true,但不会立即重新计算 - 这种延迟计算策略确保在多次同步修改依赖时只计算一次
性能优化要点
- 计算延迟:依赖变化时不立即计算,等到访问时再计算
- 值缓存:相同依赖状态下直接返回缓存值
- 依赖追踪:基于响应式系统自动管理依赖关系
- 懒执行:无访问不计算,减少不必要的性能开销
这种实现机制确保了 computed 属性既具备响应式特性,又通过智能缓存避免了重复计算,在复杂计算场景下能显著提升性能。