Vue 2 的 computed 实现原理

232 阅读3分钟

Vue.js 中的 computed 属性是一个非常有用的特性,它允许开发者声明式地定义依赖于其它数据属性的派生数据属性。当依赖的数据变化时,computed 属性会自动重新计算并缓存新的结果。这不仅提高了性能,还使得代码更加清晰和易于维护。

Vue 2 的 computed 实现原理

在 Vue 2 中,computed 属性的实现基于数据的响应式系统。当一个 computed 属性被定义时,Vue 会创建一个观察者(Watcher)对象,这个对象会跟踪依赖的数据属性的变化。具体来说:

  1. 初始化:在 computed 属性被定义时,Vue 会执行该属性的 getter 函数,并记录下所有在这个过程中访问过的数据依赖。
  2. 依赖收集:当访问这些依赖数据时,会触发这些数据的 setter 方法,从而使得 computed 属性成为这些数据的依赖者。
  3. 缓存结果:一旦 computed 属性被计算过一次,它的结果就会被缓存起来。
  4. 依赖变化:当依赖的数据发生变化时,对应的 setter 方法会被调用,这会触发依赖此数据的所有观察者的更新。
  5. 重新计算:当 computed 属性的依赖数据变化时,Vue 会重新执行 computed 属性的 getter 函数,并更新缓存的结果。
  6. 惰性求值:只有当 computed 属性被访问时,才会触发其 getter 函数的执行,如果依赖没有变化,则直接返回缓存的结果。

Vue 3 的 computed 实现原理

Vue 3 中对 computed 属性的实现进行了改进,主要体现在使用了新的响应式系统,基于 Proxy API 而不是 Object.defineProperty。这使得 computed 属性的实现更为简洁和高效。

  1. 依赖追踪:在 Vue 3 中,computed 属性通过 ref 或 reactive 创建的响应式对象来追踪依赖。当访问 computed 属性时,它会执行其 getter 函数,并通过依赖收集机制(如 track 函数)记录下所有被访问的依赖。
  2. 触发更新:当依赖的数据发生变化时,会触发相应的 effect (类似于 Vue 2 中的 Watcher),并通过 trigger 函数通知所有相关的副作用函数(side effects)重新执行。
  3. 缓存机制:Vue 3 中的 computed 属性有两种模式:getter-only 和 setter/getter。getter-only 模式的 computed 属性具有缓存机制,只有当依赖发生变化时才会重新计算。

示例代码

下面是一个简单的 Vue 2 computed 属性的例子:

javascript
new Vue({
  el: '#app',
  data: {
    firstName: 'John',
    lastName: 'Doe'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName;
    }
  }
});

在这个例子中,fullName 是一个 computed 属性,它依赖于 firstName 和 lastName。当这两个数据属性中的任何一个发生变化时,fullName 会自动更新。

总结

Vue 的 computed 属性通过响应式系统实现了对数据变化的自动追踪和重新计算。在 Vue 2 中,这一过程依赖于 Object.defineProperty 来实现数据的响应式,而在 Vue 3 中,则利用了更现代的 Proxy API 来简化实现并提高性能。无论是在哪个版本中,computed 属性都能够帮助开发者编写更简洁、更高效的代码,同时也提高了应用的性能。