vue computed实现原理
Vue computed 实现原理
Vue 的 computed 属性是基于响应式依赖的缓存机制,其核心实现依赖于 Vue 的响应式系统和 Watcher 机制。
依赖收集与缓存
computed 属性通过 Object.defineProperty 或 Proxy(Vue 3)将其定义为响应式属性。每个 computed 属性会创建一个对应的 Watcher 实例,并设置 lazy 标志为 true,表示惰性求值(仅在需要时计算)。
当首次访问 computed 属性时,会触发 getter 函数,执行计算逻辑并缓存结果。计算过程中访问的响应式数据(如 data 或 props)会通过依赖收集机制(Dep 类)将当前 Watcher 订阅到这些数据的依赖列表中。

响应式更新
当依赖的响应式数据发生变化时,会通知所有订阅的 Watcher 执行更新。对于 computed 的 Watcher,由于设置了 lazy 标志,不会立即重新计算,而是标记为 dirty(脏数据状态)。
下次访问 computed 属性时,如果 dirty 为 true,则重新执行计算逻辑并更新缓存值;否则直接返回缓存值。这种机制确保了不必要的重复计算。

代码示例(简化版)
以下是一个简化的实现逻辑(基于 Vue 2.x 的响应式系统):
class Watcher {
constructor(vm, fn, options) {
this.vm = vm;
this.getter = fn;
this.lazy = options.lazy;
this.dirty = this.lazy;
this.value = this.lazy ? undefined : this.get();
}
get() {
pushTarget(this); // 将当前 Watcher 设置为全局依赖收集目标
const value = this.getter.call(this.vm);
popTarget(); // 恢复之前的 Watcher
return value;
}
update() {
if (this.lazy) {
this.dirty = true; // 标记为脏数据,下次访问时重新计算
} else {
this.get();
}
}
evaluate() {
this.value = this.get();
this.dirty = false;
}
}
function defineComputed(vm, key, computeFn) {
const watcher = new Watcher(vm, computeFn, { lazy: true });
Object.defineProperty(vm, key, {
get() {
if (watcher.dirty) {
watcher.evaluate(); // 重新计算并更新缓存
}
return watcher.value;
}
});
}
Vue 3 的优化
在 Vue 3 中,computed 通过 Ref 和 effect 实现,底层基于 Proxy 和 WeakMap 优化依赖追踪。核心逻辑类似,但利用 Composition API 的 reactive 系统提升了性能。
import { reactive, effect } from 'vue';
function computed(getter) {
let value;
let dirty = true;
const runner = effect(getter, {
lazy: true,
scheduler: () => {
dirty = true; // 依赖变更时标记为脏数据
}
});
return {
get value() {
if (dirty) {
value = runner(); // 重新计算
dirty = false;
}
return value;
}
};
}
关键点总结
- 惰性求值:仅在访问时计算,避免不必要的性能开销。
- 依赖追踪:自动订阅计算函数中使用的响应式数据。
- 缓存机制:依赖未变化时直接返回缓存值,提升性能。
- 脏检查:依赖变化后标记为
dirty,下次访问时重新计算。






