当前位置:首页 > VUE

vue computed 实现原理

2026-01-16 19:19:36VUE

Vue Computed 实现原理

Vue 的 computed 属性是基于响应式依赖的缓存机制,其核心实现依赖于 Vue 的响应式系统和依赖收集机制。

依赖收集与缓存机制

computed 属性在初始化时会创建一个 Watcher 实例,并将 computedgetter 函数作为回调传入。当首次访问 computed 属性时,getter 函数会被执行,并在执行过程中触发依赖属性的 get 拦截器,从而将当前 Watcher 订阅到这些依赖属性的订阅列表中。

// 伪代码示例
function initComputed(vm, computed) {
  const watchers = {};
  for (const key in computed) {
    const getter = computed[key];
    watchers[key] = new Watcher(vm, getter, { lazy: true });
    defineComputed(vm, key, watchers[key]);
  }
}

惰性求值与缓存

computed 属性默认是惰性求值的,只有在被访问时才会计算值。如果依赖的响应式数据未发生变化,computed 会直接返回缓存的值,避免重复计算。

// Watcher 类中的相关逻辑
class Watcher {
  constructor(vm, expOrFn, options) {
    this.lazy = !!options.lazy;
    this.dirty = this.lazy; // 初始时为 true,表示需要重新计算
    this.getter = expOrFn;
    this.value = this.lazy ? undefined : this.get();
  }

  evaluate() {
    this.value = this.get();
    this.dirty = false;
  }

  get() {
    pushTarget(this); // 将当前 Watcher 设置为 Dep.target
    const value = this.getter.call(this.vm);
    popTarget(); // 恢复之前的 Watcher
    return value;
  }
}

依赖更新触发重新计算

computed 依赖的响应式数据发生变化时,依赖属性的 set 拦截器会通知所有订阅的 Watcher 执行更新。computedWatcher 会将 dirty 标记为 true,表示需要重新计算,但不会立即执行计算,而是等到下次访问时再重新求值。

// Watcher 更新逻辑
update() {
  if (this.lazy) {
    this.dirty = true; // 标记为脏数据,下次访问时重新计算
  } else {
    queueWatcher(this); // 非 lazy 的 Watcher 直接加入队列更新
  }
}

与模板的绑定

在模板中使用 computed 属性时,Vue 会在渲染过程中访问该属性,触发 getter 并收集依赖。如果依赖变化,会通知渲染 Watcher 重新渲染组件,从而间接触发 computed 的重新计算。

vue computed 实现原理

// 定义 computed 属性的 getter
function createComputedGetter(key) {
  return function computedGetter() {
    const watcher = this._computedWatchers[key];
    if (watcher.dirty) {
      watcher.evaluate(); // 重新计算
    }
    if (Dep.target) {
      watcher.depend(); // 收集上层 Watcher 的依赖
    }
    return watcher.value;
  };
}

总结

  • computed 通过 Watcher 实现惰性求值和缓存。
  • 依赖收集发生在首次访问时,后续访问直接返回缓存值(除非依赖变化)。
  • 依赖变化时标记为 dirty,下次访问时重新计算。
  • 与模板绑定时,会自动触发依赖收集和更新。

标签: 原理vue
分享给朋友:

相关文章

vue 实现递归

vue 实现递归

Vue 实现递归组件的方法 在 Vue 中实现递归组件通常用于处理树形结构数据,例如菜单、评论列表或文件目录。以下是实现递归组件的关键步骤: 定义递归组件 递归组件需要设置 name 属性,以便在模…

vue实现$.extend

vue实现$.extend

Vue 实现类似 jQuery 的 $.extend 功能 在 Vue 中实现类似 jQuery 的 $.extend 功能,可以通过多种方式完成。$.extend 主要用于合并多个对象的属性,Vue…

vue实现滑块

vue实现滑块

Vue 实现滑块组件的方法 使用原生 HTML 和 Vue 指令 通过 Vue 的 v-model 和事件监听实现基础滑块功能。创建一个包含 input 元素的组件,类型设置为 range,并绑定到…

vue实现listview

vue实现listview

Vue 实现 ListView 的方法 基础列表渲染 使用 v-for 指令可以轻松实现基础列表渲染。在 Vue 中,v-for 用于遍历数组或对象,生成动态列表。 <template>…

vue实现首页

vue实现首页

Vue 实现首页的基本步骤 安装 Vue.js 和相关依赖,可以通过 Vue CLI 或 Vite 快速初始化项目。Vue CLI 适合传统项目,Vite 更适合现代前端开发。 npm instal…

vue路由实现iframe

vue路由实现iframe

在Vue中实现iframe嵌入可以通过路由配置和组件动态加载来完成。以下是具体实现方法: 路由配置 在Vue Router的路由配置中,通过component属性动态加载iframe组件。需要将目标…