vue computed实现原理
Vue computed 实现原理
Vue 的 computed 属性是基于响应式依赖进行缓存的计算属性,其核心实现依赖于 Vue 的响应式系统和 Watcher 机制。
初始化阶段
在 Vue 实例初始化时,computed 属性会被遍历并转化为 getter/setter。每个 computed 属性会创建一个对应的 Watcher 实例,标记为 lazy watcher(惰性求值)。初始化时不会立即计算值,而是在首次访问时才会触发计算。
function initComputed(vm, computed) {
const watchers = vm._computedWatchers = Object.create(null);
for (const key in computed) {
const getter = typeof computed[key] === 'function'
? computed[key]
: computed[key].get;
watchers[key] = new Watcher(vm, getter, noop, { lazy: true });
defineComputed(vm, key, computed[key]);
}
}
依赖收集
当首次访问 computed 属性时,会触发 getter 函数。此时会执行 watcher.evaluate() 进行求值。在求值过程中,computed 属性所依赖的响应式数据(data/props)会被收集为依赖。这些依赖的 Dep 会将当前 computed watcher 添加到订阅列表中。
function createComputedGetter(key) {
return function computedGetter() {
const watcher = this._computedWatchers[key];
if (watcher.dirty) {
watcher.evaluate();
}
if (Dep.target) {
watcher.depend();
}
return watcher.value;
};
}
缓存机制
computed 属性具有缓存特性,只有当其依赖的响应式数据发生变化时才会重新计算。这是通过 watcher.dirty 标志位控制的。依赖数据变化时,会通知 computed watcher 将 dirty 设为 true,下次访问时重新计算。
更新触发
当 computed 依赖的响应式数据发生变化时,会触发依赖更新流程。computed watcher 会被标记为 dirty,但不会立即重新计算。只有在下次访问该 computed 属性时才会执行重新计算,这种惰性更新机制优化了性能。
与 methods 的区别
computed 属性是基于它们的响应式依赖进行缓存的,只有在相关依赖发生改变时才会重新求值。而 methods 方法每次调用都会执行函数体。对于需要复杂计算且依赖不变的情况,computed 性能更优。
与 watch 的区别
watch 更适用于在数据变化时执行异步或开销较大的操作,而 computed 更适合同步计算派生值。computed 会自动追踪依赖,而 watch 需要明确指定监听的对象。







