1. Computed 的作用与基本原理
核心概念与缓存机制
在 Vue 中,computed 计算属性用于根据已有的响应式数据派生出新的数据。它的核心特性是缓存:只有依赖变化时才会重新计算,否则会直接返回上一次的结果。这一机制让模板渲染更加高效,避免了不必要的重复运算。
当依赖的数据没有发生变化,访问 computed 属性会读取缓存值,省去了重复执行的成本。这对于涉及复杂计算或成本较高的逻辑尤为重要,能够显著提升渲染性能。
// 示例:简单的名字拼接,利用缓存机制
new Vue({el: '#app',data() {return {firstName: 'Jane',lastName: 'Doe'}},computed: {fullName() {// 只有 this.firstName 或 this.lastName 变化时才重新计算return `${this.firstName} ${this.lastName}`}}
})2. Vue 2 中的 Computed:选项式 API 实现
在 Options API 中如何定义计算属性
在 Vue 2 的 Options API 中,computed 是一个选项对象。每个属性都是一个函数,作为 getter;你也可以提供 setter,以实现双向绑定。
它实现了惰性求值、缓存和依赖跟踪,只有依赖的数据发生变化,才会触发重新计算。模板中的绑定会自动读取计算属性,就像读取普通数据一样。
new Vue({el: '#app',data() {return {firstName: 'Jane',lastName: 'Doe'}},computed: {fullName() {return `${this.firstName} ${this.lastName}`}}
})如果需要实现双向绑定,可以在计算属性中提供 Setter,使得用户输入能够反映回基础数据。
new Vue({el: '#app',data() {return {firstName: 'Jane',lastName: 'Doe'}},computed: {fullName: {get() {return `${this.firstName} ${this.lastName}`},set(value) {const [first, last] = value.split(' ')this.firstName = firstthis.lastName = last}}}
})3. Vue 3 Composition API 中的 Computed
在 Composition API 中的创建与使用方式
在 Vue 3 的 Composition API 中,computed 来自 vue 包的导出。它接收一个 getter,也可以提供 setter,用于两种方式的绑定。通过组合式 API,可以把计算属性与逻辑更灵活地组织在 setup() 中。
通常你会将响应式引用(ref)作为依赖,computed 的值会根据依赖的变化自动更新,并且与模板的绑定保持一致,简化了组件的职责划分。
import { ref, computed } from 'vue'export default {setup() {const firstName = ref('Jane')const lastName = ref('Doe')const fullName = computed(() => `${firstName.value} ${lastName.value}`)return { firstName, lastName, fullName }}
}4. 计算属性与方法、侦听器的对比
区别与适用场景
与普通方法相比,计算属性是缓存的,只要依赖没有变化,访问时将返回上次的计算结果,而不会执行函数体。这使得模板中的绑定更高效,尤其是对昂贵计算。
相比之下,方法会在每次渲染时调用,没有缓存,因此不适合耗费较大代价的计算。侦听器与 computed 的区别在于侦听器是对数据变化做副作用响应,不直接用于模板中派生数据的绑定。
// 方法示例(非缓存)
methods: {getFullName() {return `${this.firstName} ${this.lastName}`}
}// 模板中调用方法,注意每次渲染都会执行
{{ getFullName() }}

5. 计算属性的高级用法:带有 Setter 的双向绑定
Setter 的作用与使用场景
计算属性并不只有 Getter,还可以提供 Setter,实现双向绑定,常见于输入框绑定、对派生数据的间接编辑。
当模板中的用户操作修改了计算属性的值时,Setter 会被触发,你可以在 Setter 中把值映射回原始数据,保持响应性和数据的一致性。
computed: {fullName: {get() {return `${this.firstName} ${this.lastName}`},set(value) {const [first, last] = value.split(' ')this.firstName = firstthis.lastName = last}}
}6. 实战案例:列表筛选、价格格式化等
案例 1:基于输入筛选数组
在大量数据的场景中,计算属性非常适合根据搜索条件派生一个过滤后的列表,避免在方法中重复执行同样逻辑。
通过将筛选条件作为依赖,computed 会缓存结果,只有查询条件变化时才重新计算,提升性能。
export default {data() {return {query: '',items: ['apple', 'banana', 'grape', 'orange']}},computed: {filteredItems() {const q = this.query.trim().toLowerCase()if (!q) return this.itemsreturn this.items.filter(item => item.toLowerCase().includes(q))}}
}案例 2:金额格式化
将原始数值格式化为货币表示,计算属性可将数字格式化为带千分位的字符串,模板直接绑定即可,避免在模板中重复进行格式化逻辑。
computed: {formattedTotal() {const number = this.totalreturn number.toLocaleString(undefined, { style: 'currency', currency: 'CNY' })}
} 

