vue计算属性的实现
Vue 计算属性的实现原理
Vue 的计算属性(Computed Properties)是基于响应式依赖进行缓存的特性,其核心实现依赖于 Watcher 和依赖收集机制。
计算属性的初始化
在 Vue 初始化阶段,会通过 initComputed 函数处理计算属性。每个计算属性会创建一个对应的 Watcher 实例,并将计算属性的 getter 函数作为 Watcher 的求值函数。

function initComputed(vm, computed) {
const watchers = vm._computedWatchers = Object.create(null);
for (const key in computed) {
const getter = computed[key];
watchers[key] = new Watcher(
vm,
getter || function() {},
noop,
{ lazy: true } // 标记为计算属性 Watcher
);
defineComputed(vm, key, getter);
}
}
计算属性的缓存机制
计算属性通过 dirty 标志位实现缓存。当依赖的响应式数据未变化时,直接返回缓存值;当依赖变化时,标记 dirty 为 true,下次访问时重新计算。

function evaluate() {
this.value = this.get();
this.dirty = false;
}
function update() {
this.dirty = true;
}
依赖收集过程
计算属性在首次访问时会执行 getter 函数,触发依赖收集:
- 计算属性 Watcher 将自身设置为 Dep.target
- 执行 getter 函数时访问响应式数据,触发数据的 getter
- 响应式数据的 dep 会收集计算属性 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;
}
}
与普通属性的区别
- 延迟计算:只有被访问时才会计算
- 缓存机制:依赖未变化时返回缓存值
- 依赖追踪:自动追踪所有响应式依赖
实现示例代码
以下是简化版的计算属性实现:
class ComputedRef {
constructor(getter) {
this._dirty = true;
this._value = undefined;
this._getter = getter;
effect(() => this._getter(), {
scheduler: () => {
if (!this._dirty) {
this._dirty = true;
trigger(this, "value");
}
}
});
}
get value() {
if (this._dirty) {
this._value = this._getter();
this._dirty = false;
track(this, "value");
}
return this._value;
}
}
计算属性的这种实现方式确保了高效的数据更新和渲染性能,是 Vue 响应式系统的重要组成部分。






