在 Vue 2 和 Vue 3 中,watch
和 watchEffect
都是用于监听数据变化并执行副作用的 API,但它们在用法、监听方式、依赖追踪 等方面有显著区别,且 watchEffect
是 Vue 3 新增的 API(Vue 2 中不存在)。
1. 基本区别与存在版本
-
watch :
Vue 2 和 Vue 3 中均存在,是更传统的监听方式,需要明确指定要监听的数据源。
-
watchEffect :
仅存在于 Vue 3 中,是一种更简洁的监听方式,无需明确指定监听源,会自动追踪依赖。
2. 核心区别对比
特性 | watch(Vue 2/3) | watchEffect(仅 Vue 3) |
---|---|---|
监听目标 | 需明确指定监听的数据源(如 data 、computed 等) |
无需指定,自动追踪函数内部使用的响应式数据 |
初始化执行 | 默认不执行,需通过 immediate: true 配置才会初始执行 |
默认初始执行一次(收集依赖) |
依赖追踪 | 仅监听指定的数据源,若数据源是对象,需配置 deep: true 才会深度监听 |
自动追踪函数内所有响应式数据,包括对象深层属性 |
回调参数 | 回调函数接收新值、旧值两个参数((newVal, oldVal) => {} ) |
回调函数无参数,仅执行副作用逻辑 |
停止监听 | Vue 2 中通过 vm.$watch 返回的函数停止;Vue 3 中通过 watch 返回的函数停止 |
通过返回的函数停止监听 |
3. 用法示例
(1)watch 的用法(Vue 2 和 Vue 3 类似)
Vue 2 中:
js
export default {
data() {
return {
count: 0,
user: { name: "张三" },
};
},
watch: {
// 监听基本类型
count(newVal, oldVal) {
console.log(`count 从 ${oldVal} 变为 ${newVal}`);
},
// 监听对象属性(需用字符串路径)
"user.name"(newVal, oldVal) {
console.log(`用户名从 ${oldVal} 变为 ${newVal}`);
},
// 深度监听对象(监听所有属性变化)
user: {
handler(newVal) {
console.log("user 对象发生变化", newVal);
},
deep: true, // 开启深度监听
immediate: true, // 初始化时执行一次
},
},
};
Vue 3 组合式 API 中:
js
import { ref, reactive, watch } from "vue";
export default {
setup() {
const count = ref(0);
const user = reactive({ name: "张三" });
// 监听 ref
watch(count, (newVal, oldVal) => {
console.log(`count 从 ${oldVal} 变为 ${newVal}`);
});
// 监听 reactive 对象的属性
watch(
() => user.name,
(newVal, oldVal) => {
console.log(`用户名从 ${oldVal} 变为 ${newVal}`);
}
);
// 深度监听(Vue 3 中监听 reactive 对象默认深度监听)
watch(
user,
(newVal) => {
console.log("user 对象变化", newVal);
},
{ immediate: true }
);
},
};
(2)watchEffect 的用法(仅 Vue 3)
js
import { ref, reactive, watchEffect } from "vue";
export default {
setup() {
const count = ref(0);
const user = reactive({ name: "张三", age: 20 });
// 自动追踪函数内使用的响应式数据
const stop = watchEffect(() => {
// 用到了 count 和 user.name,这两个数据变化时会触发回调
console.log(`count: ${count.value}, 用户名: ${user.name}`);
});
// 3秒后停止监听
setTimeout(stop, 3000);
},
};
- 初始时会执行一次,打印初始值。
- 当
count
或user.name
变化时,会重新执行回调。 user.age
变化时不会触发,因为函数内未使用该属性(自动追踪依赖)。
4. 适用场景
-
watch :
适合需要明确知道数据变化前后的值 、只监听特定数据源 或需要控制是否深度监听/初始执行的场景。例如:监听路由变化、根据旧值和新值做不同处理。
-
watchEffect :
适合依赖较多且不需要区分新旧值的场景,写法更简洁。例如:数据变化后同步更新 DOM、发送请求等副作用操作。
总结
watch
更灵活,需手动指定监听源,可获取新旧值,适合精确控制的场景。watchEffect
更简洁,自动追踪依赖,默认初始执行,适合副作用逻辑较简单的场景。- 注意:
watchEffect
是 Vue 3 新增 API,Vue 2 中无法使用。