Vue 3 中 watch 与 watchEffect 到底怎么选?一文帮你彻底理清
前言
在 Vue 3 的 Composition API 中,watch 和 watchEffect 是两个最常用的响应式监听工具。但在实际项目开发中,很多开发者(包括刚接触 Vue 3 的我)常常在两者之间纠结:到底该用哪个?它们的底层执行机制有什么区别?本文将结合我在项目中踩过的坑,帮你彻底理清它们的用法和选择时机。
核心区别:按需监听 vs 自动追踪
要搞懂它们的区别,我们只需要记住一句话:watch 是“你指哪我打哪”,而 watchEffect 是“我自动帮你找目标”。
- watch:显式声明,精准打击
watch 需要你明确指定要监听的数据源。只有当这个数据发生变化时,回调函数才会执行。
适用场景:你需要知道“变化前”和“变化后”的值,或者只想在某个特定变量改变时触发逻辑(如路由参数变化时重新请求数据)。`import { ref, watch } from ‘vue’;
const keyword = ref(‘’);
// 明确监听 keyword
watch(keyword, (newVal, oldVal) => {
console.log(搜索词从 ${oldVal} 变成了 ${newVal});
fetchData(newVal);
});`
2. watchEffect:自动收集依赖,即插即用
watchEffect 不需要你指定数据源。它会在首次执行时,自动追踪内部用到的所有响应式变量。只要其中任何一个变了,它就会重新执行。
适用场景:你只关心“执行某个副作用”,不关心具体是哪个变量变了,也不需要旧值(如自动同步状态到本地存储、自动发起网络请求)。
import{ref,watchEffect}from'vue';constuserId=ref(1);consttoken=ref('abc');// 自动追踪 userId 和 tokenwatchEffect(()=>{console.log('重新获取用户信息:',userId.value,token.value);fetchUserInfo(userId.value,token.value);});项目实战:我踩过的坑与最佳实践
坑点:在 watchEffect 中误用异步回调
watchEffect 只能同步收集依赖。如果你在异步回调(如 setTimeout 或 Promise.then)里读取响应式变量,它是无法追踪到的!`// ❌ 错误示范:watchEffect 不会监听 count 的变化
watchEffect(() => {
setTimeout(() => {
console.log(count.value); // 依赖收集失败!
}, 1000);
});
// ✅ 正确做法:在 watchEffect 外部同步读取,或者改用 watch
watchEffect(() => {
const currentCount = count.value; // 同步读取,成功收集依赖
setTimeout(() => {
console.log(currentCount);
}, 1000);
});坑点:watchEffect 导致的无限循环 如果在 watchEffect 内部修改了它自己追踪的变量,就会触发无限循环。// ❌ 危险操作
watchEffect(() => {
list.value = list.value.filter(item => item.isActive);
});`
总结:一图流选择指南
需要旧值? 👉 选 watch
只监听单一/特定几个变量? 👉 选 watch
初始化时需要立即执行一次? 👉 选 watchEffect (或 watch 加 { immediate: true })
逻辑简单,不想写一堆数据源? 👉 选 watchEffect
