Appearance
什么是计算属性?
计算属性(computed)是一类特殊的属性,它的值由其他数据计算得出,而且 Vue 会缓存结果。 简单说:有依赖别人才能算出来的值,就放 computed 里。
一个例子看懂
vue
<template>
<p>原始数组:{{ numbers }}</p>
<p>偶数数组:{{ evenNumbers }}</p>
</template>
<script>
export default {
data() {
return {
numbers: [1, 2, 3, 4, 5, 6]
}
},
computed: {
evenNumbers() {
return this.numbers.filter(n => n % 2 === 0)
}
}
}
</script>
输出:
原始数组:[1, 2, 3, 4, 5, 6]
偶数数组:[2, 4, 6]
evenNumbers 不是存死的数据,而是每次根据 numbers 自动算出来的。只要 numbers 不变,evenNumbers 就用缓存的结果,不会重新算。
计算属性 vs 方法 — 关键区别
两种写法都能实现同样的功能,但行为完全不同:
vue
<template>
<!-- 方法:每次访问都会重新执行 -->
<p>{{ getEvenNumbers() }}</p>
<p>{{ getEvenNumbers() }}</p>
<p>{{ getEvenNumbers() }}</p>
<!-- 计算属性:第一次算出后缓存,后面直接用 -->
<p>{{ evenNumbers }}</p>
<p>{{ evenNumbers }}</p>
<p>{{ evenNumbers }}</p>
</template>
<script>
export default {
data() { return { numbers: [1, 2, 3, 4, 5, 6] } },
computed: {
evenNumbers() {
console.log('computed 被调用了') // 只打印 1 次
return this.numbers.filter(n => n % 2 === 0)
}
},
methods: {
getEvenNumbers() {
console.log('method 被调用了') // 打印 3 次
return this.numbers.filter(n => n % 2 === 0)
}
}
}
</script>
| computed | methods | |
|---|---|---|
| 缓存 | 有(依赖不变就复用上次结果) | 无(每次重新计算) |
| 调用方式 | 像属性一样,不带括号:{{ evenNumbers }} | 像函数一样,带括号:{{ getEvenNumbers() }} |
| 适用场景 | 需要根据数据计算的展示值 | 需要执行的动作(如事件处理) |
| 何时用 | 读数据时 | 做操作时 |
| 💡 Tip:记住 | ||
computed 就像 Excel 里的公式:=SUM(A1:A10)。只要 A1:A10 的值没变,结果就不会重新算。 |
计算属性的 getter 和 setter
计算属性默认是"只读"的(getter)。但你也可以让它可写(setter):
vue
<template>
<p>{{ fullName }}</p>
<button @click="changeFullName">改名字</button>
</template>
<script>
export default {
data() {
return {
firstName: '张',
lastName: '三'
}
},
computed: {
fullName: {
get() { // 读取时调用
return this.firstName + this.lastName
},
set(newValue) { // 设置时调用
this.firstName = newValue[0]
this.lastName = newValue.slice(1)
}
}
},
methods: {
changeFullName() {
this.fullName = '李四' // 触发 setter
}
}
}
</script>
不过 getter+setter 的计算属性用得比较少,大部分场景下只读就够了。
什么时候用 computed?
凡是符合"这个值由其他值决定"的逻辑,都应该用 computed:
- 过滤列表(如搜索功能)
- 格式化显示(如价格显示为 ¥ 符号)
- 判断状态(如购物车是否为空)
- 拼接字符串(如全名 = 姓 + 名)
新手常见问题
Q:computed 里能写异步代码吗? A:不行。computed 是同步的,必须立即返回值。如果需要异步操作,用 watch 或 methods。 Q:computed 里能修改 data 吗? A:不能!computed 是"只读"的,在里面修改 data 会造成无限循环。改数据去 methods。 下一步: 💡 Tip:Composition API 写法(Vue 3)
vue
<script setup>
import { ref, computed } from 'vue'
const numbers = ref([1, 2, 3, 4, 5, 6])
const evenNumbers = computed(() => numbers.value.filter(n => n % 2 === 0))
</script>
详见: