Vue 3 computed 原理解析总结
Vue 3 的 computed 是基于 观察者模式(Observer Pattern) 和 惰性求值(Lazy Evaluation) 实现的响应式数据派生机制,其核心原理可总结如下:
- 核心角色
角色 Vue 3 对应部分 作用
Subject(被观察者) ref / reactive 数据(如 count) 存储数据,并在变更时通知观察者
Observer(观察者) computed 的 ReactiveEffect 订阅依赖数据,并在数据变化时标记自身为 dirty
Dependency(依赖管理器) Vue 的 depsMap 系统 记录 computed 与响应式数据的订阅关系
- 核心流程
(1) 创建computed
javascript
const count = ref(0);
const double = computed(() => count.value * 2);
- 初始化:
- 将计算函数
() => count.value * 2包装成ReactiveEffect(观察者)。 dirty初始为true(首次访问必须计算)。
- 将计算函数
(2) 首次访问(依赖收集)
javascript
console.log(double.value); // 触发计算
- 执行计算函数,读取
count.value。 count的getter检测到当前有活动的effect(即double的ReactiveEffect),将其加入自己的依赖列表(deps)。- 计算结果(
0)并缓存,dirty设为false。
(3) 依赖数据变更
javascript
count.value++; // 修改数据
count的setter触发,遍历所有订阅它的effect(即double的ReactiveEffect)。- 将
double标记为dirty: true(但不立即计算,惰性更新)。
(4) 再次访问(惰性更新)
javascript
console.log(double.value); // 重新计算
- 检查
dirty:- 若
dirty === true→ 重新执行计算函数,更新缓存,dirty设为false。 - 若
dirty === false→ 直接返回缓存值(跳过计算)。
- 若
- 返回最新结果(
2)。
- 关键机制
机制 作用 优势
dirty 标志位 控制是否重新计算 避免同一事件循环内的重复计算,提升性能
惰性求值(Lazy) 只有访问时才计算 节省资源,避免不必要的计算
动态依赖收集 每次执行计算函数时重新收集依赖 自动适应条件分支(如 if 语句)
缓存机制 依赖未变化时直接返回旧值 减少重复计算,提高效率
- 与
watch的区别
特性computedwatch/watchEffect
触发时机 惰性(读取时计算) 立即(依赖变化立即执行)
缓存 ✅ 有缓存 ❌ 无缓存
适用场景 派生数据(如过滤、计算属性) 副作用(如请求数据、DOM 操作)
- 总结
computed是一个观察者,订阅其依赖的响应式数据(如ref/reactive)。- 依赖变化时,仅标记
dirty: true,不立即计算(惰性更新)。 - 下次访问时,若
dirty则重新计算,否则返回缓存值。 - 优势:自动依赖跟踪、精确更新、高性能缓存。
一句话总结:
computed 通过观察者模式 + dirty 标志位 + 惰性求值,实现高效、精确的派生数据管理。 🚀

浙公网安备 33010602011771号