一、核心机制对比
特性 | Computed(计算属性) | Watch(侦听器) |
---|---|---|
原理 | 基于依赖的响应式缓存 | 观察特定数据变化,触发回调函数 |
触发时机 | 依赖的响应式数据变化时自动计算 | 被侦听的特定数据变化时触发 |
返回值 | 必须有返回值,用于模板渲染或逻辑处理 | 无返回值,用于执行副作用操作(如异步请求、DOM操作) |
异步支持 | ❌ 不能执行异步操作 | ✅ 支持异步操作 |
缓存机制 | ✅ 依赖未变化时直接返回缓存结果,高效 | ❌ 无缓存,每次变化都执行回调 |
适用场景 | 模板中需要复杂逻辑处理的数据 | 数据变化时需要执行特定操作(如接口请求、复杂逻辑) |
二、使用场景及代码示例
1. Computed 适用场景
场景特点:需要基于现有数据 派生新值,且依赖数据变化时需要 自动更新。
示例 1:格式化显示数据
<template>
<div>全名:{{ fullName }}</div>
</template>
<script>
export default {
data() {
return { firstName: '张', lastName: '三' };
},
computed: {
fullName() {
return this.firstName + '·' + this.lastName; // 自动拼接
}
}
};
</script>
示例 2:过滤列表数据
<template>
<div v-for="item in filteredList" :key="item.id">{{ item.name }}</div>
</template>
<script>
export default {
data() {
return {
list: [/* 原始数据 */],
searchText: ''
};
},
computed: {
filteredList() {
return this.list.filter(item =>
item.name.includes(this.searchText)
);
}
}
};
</script>
2. Watch 适用场景
场景特点:需要在数据变化时 执行异步操作 或 复杂副作用。
示例 1:搜索输入防抖(异步操作)
<script>
export default {
data() {
return { searchText: '' };
},
watch: {
searchText(newVal) {
// 防抖处理,避免频繁请求
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.fetchData(newVal);
}, 500);
}
},
methods: {
fetchData(keyword) { /* 发起请求 */ }
}
};
</script>
示例 2:深度监听对象变化
<script>
export default {
data() {
return { user: { name: 'Alice', age: 25 } };
},
watch: {
user: {
handler(newVal) {
console.log('用户信息变化:', newVal);
},
deep: true, // 深度监听对象内部变化
immediate: true // 立即触发一次
}
}
};
</script>
三、Vue 3 中的变化(Composition API)
1. Computed
import { ref, computed } from 'vue';
const firstName = ref('张');
const lastName = ref('三');
const fullName = computed(() => {
return firstName.value + '·' + lastName.value;
});
2. Watch
import { ref, watch } from 'vue';
const searchText = ref('');
watch(searchText, (newVal, oldVal) => {
// 执行异步操作
fetchData(newVal);
});
// 监听多个源
watch([source1, source2], ([new1, new2], [old1, old2]) => {});
3. WatchEffect(自动依赖追踪)
import { watchEffect } from 'vue';
watchEffect(() => {
// 自动追踪函数内使用的响应式变量
console.log('searchText变化:', searchText.value);
});
四、性能优化建议
- 优先使用 Computed
- 避免在模板中写复杂逻辑,用 Computed 缓存结果。
- 避免深度监听(Watch)的开销
- 必要时使用
deep: true
,但需注意性能影响。
- 必要时使用
- 及时清理副作用
- 在组件销毁前,清除定时器或取消未完成的异步操作(如
clearTimeout
)。
- 在组件销毁前,清除定时器或取消未完成的异步操作(如
五、总结
维度 | Computed | Watch |
---|---|---|
核心目的 | 派生数据(模板渲染、数据格式化) | 响应数据变化(执行副作用操作) |
缓存 | 有缓存,依赖不变时复用结果 | 无缓存,每次变化都执行 |
异步 | 不支持 | 支持 |
适用场景 | 模板中的复杂逻辑、数据过滤/聚合 | 数据变化时需要异步操作或触发其他行为 |
选择原则:
- 需要派生数据 → 用
computed
。 - 需要响应变化执行操作 → 用
watch
。 - Vue 3 组合式 API → 灵活使用
computed
、watch
和watchEffect
。
经典场景:
- 计算总价、格式化日期 →
computed
。 - 搜索框输入防抖、路由参数变化重新加载数据 →
watch
。