当前位置:首页 > VUE

vue computed的实现

2026-02-19 22:24:14VUE

Vue computed 的实现原理

Vue 的 computed 属性是基于响应式依赖进行缓存的计算属性,其实现主要依赖于 Vue 的响应式系统和 Watcher 机制。

核心实现步骤

初始化 computed 属性

在 Vue 实例初始化时,computed 属性会被遍历并定义为响应式属性。每个 computed 属性会创建一个对应的 Watcher 实例,并将 computed 的 getter 函数作为 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 } // 标记为 computed watcher
    );
    defineComputed(vm, key, computed[key]);
  }
}

定义 computed 属性

通过 Object.defineProperty 将 computed 属性代理到 Vue 实例上,并重写 getter 和 setter。

function defineComputed(target, key, def) {
  const shouldCache = !isServerRendering();
  if (typeof def === 'function') {
    def = { get: def };
  }
  Object.defineProperty(target, key, {
    enumerable: true,
    configurable: true,
    get: shouldCache
      ? createComputedGetter(key)
      : def.get,
    set: def.set || noop
  });
}

computed getter 的实现

vue computed的实现

当访问 computed 属性时,会触发 getter 函数。该函数会检查依赖是否变化,决定是否重新计算值。

function createComputedGetter(key) {
  return function computedGetter() {
    const watcher = this._computedWatchers && this._computedWatchers[key];
    if (watcher) {
      if (watcher.dirty) {
        watcher.evaluate(); // 重新计算值
      }
      if (Dep.target) {
        watcher.depend(); // 收集依赖
      }
      return watcher.value;
    }
  };
}

Watcher 的更新机制

computed watcher 在初始化时会被标记为 lazy,首次不会立即求值。当依赖的响应式数据变化时,会触发 watcher 的更新,但不会立即重新计算,而是标记为 dirty,等到下次访问时再重新计算。

class Watcher {
  constructor(vm, expOrFn, cb, options) {
    this.lazy = !!options.lazy;
    this.dirty = this.lazy;
    if (typeof expOrFn === 'function') {
      this.getter = expOrFn;
    }
    this.value = this.lazy ? undefined : this.get();
  }

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

  update() {
    if (this.lazy) {
      this.dirty = true; // 标记为脏,下次访问时重新计算
    } else {
      this.run();
    }
  }
}

关键设计点

缓存机制

vue computed的实现

computed 属性会根据依赖是否变化来决定是否重新计算。只有当依赖变化时,才会在下一次访问时重新计算,否则直接返回缓存值。

依赖收集

在 computed getter 执行时,会触发依赖的响应式数据的 getter,从而将当前的 computed watcher 收集为依赖。当这些依赖变化时,会通知 computed watcher 更新。

惰性求值

computed 属性在首次访问时才会进行计算,并且只有在依赖变化后再次访问时才会重新计算,这种惰性求值机制提高了性能。

标签: vuecomputed
分享给朋友:

相关文章

vue实现关键词轮播

vue实现关键词轮播

Vue 实现关键词轮播 基础实现方案 使用 Vue 的 v-for 和 setInterval 实现基础轮播效果: <template> <div class="keyword…

vue实现详情

vue实现详情

Vue 实现详情页的常见方法 使用动态路由 在 Vue Router 中配置动态路由参数,通过 $route.params 获取详情 ID。示例路由配置: { path: '/detail/:i…

vue 实现流程

vue 实现流程

Vue 实现流程 Vue.js 是一个渐进式 JavaScript 框架,用于构建用户界面。以下是 Vue 实现的基本流程: 安装 Vue.js 通过 CDN 引入或使用 npm/yarn 安装:…

vue实现tip

vue实现tip

Vue实现Tooltip的方法 使用Vue实现Tooltip可以通过多种方式完成,以下是几种常见的方法: 使用原生HTML的title属性 在Vue模板中直接使用HTML的title属性是最简单的实…

自己实现vue

自己实现vue

实现简易版 Vue.js 核心功能 要实现一个简易版 Vue.js,需要理解其核心功能:数据响应式、模板编译、依赖收集和虚拟 DOM。以下分模块实现关键功能。 数据响应式(Reactivity) 通…

vue实现图片预览

vue实现图片预览

Vue 实现图片预览的方法 使用 Element UI 的 el-image 组件 Element UI 提供了 el-image 组件,支持图片预览功能。通过设置 preview-src-list…