Vue.js 中的 computed 属性是一个非常有用的特性,它允许开发者声明式地定义依赖于其它数据属性的派生数据属性。当依赖的数据变化时,computed 属性会自动重新计算并缓存新的结果。这不仅提高了性能,还使得代码更加清晰和易于维护。
Vue 2 的 computed 实现原理
在 Vue 2 中,computed 属性的实现基于数据的响应式系统。当一个 computed 属性被定义时,Vue 会创建一个观察者(Watcher)对象,这个对象会跟踪依赖的数据属性的变化。具体来说:
- 初始化:在
computed属性被定义时,Vue 会执行该属性的 getter 函数,并记录下所有在这个过程中访问过的数据依赖。 - 依赖收集:当访问这些依赖数据时,会触发这些数据的 setter 方法,从而使得
computed属性成为这些数据的依赖者。 - 缓存结果:一旦
computed属性被计算过一次,它的结果就会被缓存起来。 - 依赖变化:当依赖的数据发生变化时,对应的 setter 方法会被调用,这会触发依赖此数据的所有观察者的更新。
- 重新计算:当
computed属性的依赖数据变化时,Vue 会重新执行computed属性的 getter 函数,并更新缓存的结果。 - 惰性求值:只有当
computed属性被访问时,才会触发其 getter 函数的执行,如果依赖没有变化,则直接返回缓存的结果。
Vue 3 的 computed 实现原理
Vue 3 中对 computed 属性的实现进行了改进,主要体现在使用了新的响应式系统,基于 Proxy API 而不是 Object.defineProperty。这使得 computed 属性的实现更为简洁和高效。
- 依赖追踪:在 Vue 3 中,
computed属性通过ref或reactive创建的响应式对象来追踪依赖。当访问computed属性时,它会执行其 getter 函数,并通过依赖收集机制(如track函数)记录下所有被访问的依赖。 - 触发更新:当依赖的数据发生变化时,会触发相应的
effect(类似于 Vue 2 中的 Watcher),并通过trigger函数通知所有相关的副作用函数(side effects)重新执行。 - 缓存机制: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 属性都能够帮助开发者编写更简洁、更高效的代码,同时也提高了应用的性能。