Vue3中计算属性computed
一、computed 的核心特性
- 依赖缓存
基于响应式依赖自动缓存计算结果,只有依赖项变化时才会重新计算 - 声明式编程
将复杂计算逻辑封装为可读性高的属性,避免模板中出现复杂表达式 - 自动追踪依赖
Vue 自动追踪计算属性依赖的响应式数据,无需手动管理更新 - 懒计算机制
依赖变化后不会立即计算,直到下次被访问时才重新求值
二、基础用法(组合式 API)
1. 简单计算
<script setup>
import { ref, computed } from 'vue'
const price = ref(100)
const quantity = ref(2)
// 计算总价
const total = computed(() => price.value * quantity.value)
</script>
<template>
<p>单价:{{ price }}</p>
<p>数量:{{ quantity }}</p>
<p>总价:{{ total }}</p>
</template>
2. 多依赖计算
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('张')
const lastName = ref('三')
// 组合全名
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
</script>
三、高级用法
1. 可写计算属性(setter)
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('李')
const lastName = ref('四')
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`
},
set(newValue) {
[firstName.value, lastName.value] = newValue.split(' ')
}
})
// 修改示例
setTimeout(() => {
fullName.value = '王 五' // 自动触发setter
}, 2000)
</script>
2. 链式计算
<script setup>
import { ref, computed } from 'vue'
const basePrice = ref(100)
const taxRate = ref(0.1)
// 计算含税价
const tax = computed(() => basePrice.value * taxRate.value)
const totalPrice = computed(() => basePrice.value + tax.value)
</script>
四、与 methods 的对比
特性 | computed | methods |
---|---|---|
缓存机制 | ✅ 自动缓存 | ❌ 每次调用执行 |
模板调用方式 | 属性访问 | 方法调用 |
响应式依赖追踪 | ✅ 自动 | ❌ 手动管理 |
适用场景 | 纯计算逻辑 | 需要主动触发的操作 |
五、实战案例
1. 购物车计算(多级依赖)
<script setup>
import { ref, computed } from 'vue'
const cartItems = ref([
{ name: '商品A', price: 199, quantity: 2 },
{ name: '商品B', price: 299, quantity: 1 }
])
// 商品总数
const totalQuantity = computed(() =>
cartItems.value.reduce((sum, item) => sum + item.quantity, 0)
)
// 总金额(含运费)
const subtotal = computed(() =>
cartItems.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
)
const shippingFee = computed(() => subtotal.value > 500 ? 0 : 30)
const grandTotal = computed(() => subtotal.value + shippingFee.value)
</script>
2. 数据格式化
<script setup>
import { ref, computed } from 'vue'
const timestamp = ref(1677628800000)
// 日期格式化
const formattedDate = computed(() => {
const date = new Date(timestamp.value)
return `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`
})
</script>
六、最佳实践
- 保持纯函数
避免在计算属性中修改外部状态或执行异步操作 - 命名规范
使用形容词(如sortedList
)或名词短语(如totalPrice
) - 性能优化
对于复杂计算,优先使用 computed 替代 methods - 避免副作用
不要在 getter 中修改依赖数据,可能导致无限循环 - 组合使用
可将多个简单计算属性组合成复杂计算逻辑
七、常见问题
Q:何时该用 watch 替代 computed?
A:当需要执行异步操作或复杂副作用时使用 watch,纯计算场景用 computed
Q:computed 可以依赖其他 computed 吗?
A:可以,Vue 会自动建立依赖链(参见示例中的链式计算)
Q:为什么我的计算属性没有更新?
A:检查依赖项是否为响应式数据,确保通过 .value
访问 ref 值
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 万家灯火