模式切换
计算属性(computed)和侦听器(watch)
计算属性和侦听器是 Vue 响应式系统中的核心功能,用于处理依赖数据的逻辑和副作用。以下是它们的详细对比和使用场景:
计算属性(computed)
作用
- 基于依赖数据动态计算值,并缓存结果。
- 只有当依赖的响应式数据变化时,才会重新计算。
语法
javascript
import { ref, computed } from 'vue';
const firstName = ref('张');
const lastName = ref('三');
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
特点
缓存机制
- 只有当
firstName
或lastName
变化时,fullName
才会重新计算。 - 多次访问
fullName
直接返回缓存值,避免重复计算。
- 只有当
只读性
默认生成的是只读属性,不能直接赋值。
如需可写,需提供
get
和set
:javascriptconst fullName = computed({ get() { return `${firstName.value} ${lastName.value}`; }, set(newValue) { [firstName.value, lastName.value] = newValue.split(' '); } });
适用场景
- 模板中需要复杂逻辑计算的表达式(如过滤列表、格式化数据)。
- 避免在模板中写复杂逻辑,保持代码清晰。
示例
html
<template>
<p>全名:{{ fullName }}</p>
</template>
侦听器(watch)
作用
- 监听响应式数据的变化,执行副作用(如异步请求、DOM 操作)。
- 适合处理数据变化后的异步或复杂逻辑。
语法
javascript
import { ref, watch } from 'vue';
const count = ref(0);
const user = ref({ name: 'Alice' });
// 监听单个 ref
watch(count, (newVal, oldVal) => {
console.log(`count 变化:${oldVal} → ${newVal}`);
});
// 监听嵌套属性
watch(
() => user.value.name,
(newName) => {
console.log(`用户名变为 ${newName}`);
}
);
// 监听多个源
watch([count, () => user.value.name], ([newCount, newName]) => {
console.log(`count或name变化:${newCount}, ${newName}`);
});
特点
惰性执行
- 默认不会立即执行,只有在监听的数据变化时触发。
- 通过
{ immediate: true }
强制立即执行一次。
深度监听
默认不监听对象内部变化,需设置
{ deep: true }
:javascriptwatch(user, (newVal) => { console.log('user 变化', newVal); }, { deep: true });
停止监听
组合式 API 中,
watch
返回一个停止函数:javascriptconst stop = watch(count, () => { /*...*/ }); stop(); // 手动停止监听
适用场景
- 数据变化时需要执行异步操作(如搜索请求)。
- 监听路由或状态变化后执行逻辑。
示例
javascript
// 搜索框输入防抖
const searchQuery = ref('');
watch(searchQuery, (newQuery) => {
fetchResults(newQuery); // 模拟 API 请求
}, { debounce: 300 }); // 300ms 防抖
computed 和 watch 对比
特性 | computed | watch |
---|---|---|
目的 | 派生新数据(基于依赖计算) | 监听数据变化执行副作用 |
返回值 | 必须返回一个值 | 无返回值(通常执行异步操作) |
缓存 | ✅ 自动缓存结果 | ❌ 每次变化都触发 |
异步支持 | ❌ 不能包含异步逻辑 | ✅ 适合异步操作 |
典型场景 | 模板中的动态计算(如全名) | 数据变化后调 API、操作 DOM |
如何选择?
用
computed
当:- 需要基于其他数据 动态计算一个值(如过滤列表、格式化显示)。
- 希望利用缓存优化性能。
用
watch
当:- 需要在数据变化时 执行副作用(如请求 API、存储到 localStorage)。
- 需要监听 非响应式数据(如路由参数)。
组合使用示例
javascript
import { ref, computed, watch } from 'vue';
const price = ref(100);
const quantity = ref(2);
// 计算总价(自动缓存)
const total = computed(() => price.value * quantity.value);
// 监听总价变化
watch(total, (newTotal) => {
console.log('总价更新:', newTotal);
if (newTotal > 500) {
alert('金额过大!');
}
});
总结
computed
:- 计算派生数据,适合模板中使用。
- 自动缓存,高效响应依赖变化。
watch
:- 监听数据变化,执行异步或副作用逻辑。
- 支持深度监听、防抖等高级功能。