跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

组合式 API 中计算属性的底层实现原理,带你通过源码看清 Effect

computed本质是lazy effect,创建时不执行也不收集依赖,首次读取.value时才运行并建立响应式依赖,后续变更仅标记dirty,下次读取时才重新计算并缓存结果。 计算属性( computed )在组合式 API 中并非简单封装的 getter,而是基于响应式系统核心—— Effect 构建的惰性、可缓存的依赖追踪视图。它的本质是一个“被包装过的响应式副作用”,其重计算时机、缓存策略和依赖收集逻辑,全部由
effect
的调度机制与
ReactiveEffect
实例行为决定。 computed 本质是一个 lazy effect 调用
computed(() => x.value + y.value)
时,Vue 并不立即执行函数,而是创建一个
ReactiveEffect
实例,并将其
lazy
标志设为
true
: 该 effect 不会自动运行,也不在创建时收集依赖 只有当外界首次读取
computedRef.value
时,才触发
effect.run()
,此时才真正执行 getter 并建立响应式依赖关系 后续依赖变化时,effect 不会自动重新运行,而是标记自身为“脏”(
dirty = true
),等待下一次
.value
访问时才重新求值 依赖收集发生在第一次 .value 读取时 computed 内部持有一个
runner
(即 lazy effect 的执行函数),并在其
get value
访问器中做如下关键操作: 若
dirty === true
,则调用
runner()
执行 getter,此时
track
开始工作,将当前 activeEffect(即该 computed 的 effect)加入所访问响应式属性(如
x.value
)的依赖列表 执行结果被缓存到
_value
,
dirty
置为
false
若依赖未变,后续读取直接返回缓存值,跳过 getter 执行 依赖变化时仅标记为脏,不立即更新 当
x.value
被修改,触发其
trigger
流程时: 会遍历所有依赖于
x
的 effects,对其中是 computed effect 的,只执行
effect.scheduler
computed 的 scheduler 就是
() => (dirty = true)
,不做重计算,只标记自己失效 这保证了 computed 的惰性:多次依赖变更只标记一次脏,直到下次读取才合并计算,避免冗余执行 ref 接口背后是 ReactiveEffect + 响应式缓存 computed 返回的是一个
ComputedRefImpl
实例,它同时实现了
Ref
和
Getter
行为:
.value
是响应式访问器:读取时触发依赖收集或缓存返回;写入(仅可写 computed)时调用 setter 并触发 trigger 内部
_value
缓存与
dirty
标志协同,实现“有需才算”的语义 整个生命周期完全复用
effect
的 track/trigger/scheduler 三件套,没有额外的响应式层 不复杂但容易忽略:computed 不是“监听器”,也不是“自动刷新变量”,它是 effect 的一种受控使用方式——用 lazy + scheduler + 缓存,把响应式求值变成按需调用的纯函数接口。

相关文章