Vue学习笔记集--computed
computed
在 Vue 3 的 Composition API 中,computed
用于定义响应式计算属性
它的核心特性是自动追踪依赖、缓存计算结果(依赖未变化时不会重新计算)
基本用法
1. 定义只读计算属性
import { ref, computed } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2); // 返回一个 Ref 对象
console.log(doubleCount.value); // 0 → 初始值
count.value = 2;
console.log(doubleCount.value); // 4 → 自动更新
2. 在模板中使用
<template>
<div>{{ doubleCount }}</div> <!-- 自动解包,无需 .value -->
</template>
computed
的响应式依赖
- 自动追踪依赖:计算属性会追踪其内部使用的所有响应式变量(如
ref
或reactive
)。 - 缓存机制:只有依赖变化时才会重新计算,否则直接返回缓存值。
const a = ref(1);
const b = ref(2);
const sum = computed(() => a.value + b.value);
a.value = 3; // sum 自动重新计算 → 3 + 2 = 5
b.value = 4; // sum 再次计算 → 3 + 4 = 7
可写计算属性(Setter)
computed
可以接受一个包含 get
和 set
的对象,实现双向绑定:
const firstName = ref('John');
const lastName = ref('Doe');
// 可写计算属性
const fullName = computed({
get: () => `${firstName.value} ${lastName.value}`,
set: (newValue) => {
const [first, last] = newValue.split(' ');
firstName.value = first;
lastName.value = last;
},
});
// 修改计算属性
fullName.value = 'Jane Smith'; // 自动更新 firstName 和 lastName
console.log(firstName.value); // 'Jane'
console.log(lastName.value); // 'Smith'
与 reactive
结合使用
将计算属性绑定到 reactive
对象中:
import { reactive, computed } from 'vue';
const state = reactive({
price: 100,
quantity: 2,
});
// 计算总价
state.total = computed(() => state.price * state.quantity);
console.log(state.total.value); // 200
性能优化:避免重复计算
计算属性会缓存结果,以下场景体现优势:
const list = ref([1, 2, 3, 4, 5]);
// 计算过滤后的列表(只有 list 变化时重新计算)
const evenNumbers = computed(() => list.value.filter(num => num % 2 === 0));
list.value.push(6); // evenNumbers 自动更新为 [2,4,6]
注意事项
-
避免副作用:计算属性应是纯函数,不要在其中修改外部状态。
// ❌ 错误示例(副作用) const invalidComputed = computed(() => { count.value++; // 禁止修改依赖! return count.value; });
-
依赖非响应式数据:如果依赖非响应式变量,计算属性不会更新:
let staticValue = 10; const badComputed = computed(() => staticValue); // 不会更新!
-
性能敏感场景:复杂计算建议使用
computed
缓存结果,而非在模板中直接调用方法。
与 Vue 2 的对比
特性 | Vue 2 的 computed | Vue 3 的 computed |
---|---|---|
定义位置 | computed 选项 | 在 setup 中通过函数定义 |
返回值类型 | 直接通过属性访问 | Ref 对象(需 .value 访问) |
响应式依赖追踪 | 自动 | 自动 |
可写性 | 不支持 Setter | 支持 Setter |
完整示例
<template>
<div>
<input v-model="price" type="number" placeholder="价格">
<input v-model="quantity" type="number" placeholder="数量">
<p>总价: {{ total }}</p>
<button @click="resetTotal">重置总价</button>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const price = ref(0);
const quantity = ref(0);
// 计算总价
const total = computed({
get: () => price.value * quantity.value,
set: (value) => {
price.value = value / 2;
quantity.value = 2;
},
});
// 通过 Setter 修改计算属性
const resetTotal = () => {
total.value = 0; // 触发 Setter → price=0, quantity=0
};
</script>