Vue 2 和 Vue 3 中的 watch 机制在核心功能上相似,但语法、灵活性和底层实现有显著差异。以下是主要区别的详细对比:
1. 基本用法与语法
-
Vue 2 :
watch是一个选项(option),通常作为组件配置对象中的一个属性。它是一个对象,键是需要监听的数据表达式,值是回调函数或包含选项的对象。-
例如:
<template>count: name:</template> <script> export default { data() { return { count: 0, user: { name: 'John' } }; }, watch: { count(newVal, oldVal) { console.log(`count changed from ${oldVal} to ${newVal}`); }, 'user.name': function(newVal, oldVal) { console.log(`name changed from ${oldVal} to ${newVal}`); }, user: { handler(newVal, oldVal) { console.log('user changed:', newVal); }, deep: true, immediate: true } }, methods: { decrementCount() { this.count--; }, resetUser() { this.user.name += '--'; } } }; </script>
<button @click="count++">+</button> <button @click="decrementCount">-</button> <button @click="resetUser">Reset User</button>
-
-
Vue 3 :
watch是一个函数,需要从vue库中导入。它更灵活,支持监听ref、reactive对象、getter 函数等多种数据源。 -
例如:
<template>count: name:
<button @click="count++">+</button> <button @click="changUser">修改user</button></template> <script setup lang="ts"> import { ref, reactive, watch } from 'vue'; const count = ref(0); const user = reactive({ name: 'John' }); watch(count, (newVal, oldVal) => { console.log(`count changed from ${oldVal} to ${newVal}`); }); watch(() => user.name, (newVal, oldVal) => { console.log(`name changed from ${oldVal} to ${newVal}`); });</div>function changUser() {
user.name = 'Tom';
}
</script>2. 监听源的指定方式
- Vue 2:必须明确指定监听的数据源(如 count 或 'user.name'),支持字符串路径监听对象属性。
- Vue 3:支持更灵活的监听源,包括:
- ref 对象(如 count)。
- reactive 对象(如 user,默认深度监听)。
- getter 函数(如 () => user.name),允许监听复杂表达式。
例如,监听多个源:
watch([() => count.value, () => user.name], ([newCount, newName], [oldCount, oldName]) => { console.log(`count: ${newCount}, name: ${newName}`); });3. 立即执行与副作用处理
- 立即执行 :
- Vue 2 的
watch默认惰性执行(仅在数据变化时触发),但可通过immediate: true选项初始化时执行一次。12 - Vue 3 的
watch同样默认惰性,但immediate选项用法一致。13
- Vue 2 的
- 副作用清理 :
-
Vue 3 的
watch支持在回调中使用onCleanup函数清理副作用(如取消定时器或网络请求),避免内存泄漏。watch(data, async (newVal, oldVal, onCleanup) => {
let cancelled = false;
onCleanup(() => { cancelled = true; });
const result = await fetchData(newVal);
if (!cancelled) { /* 处理结果 */ }
});
-
4. 与
watchEffect的关系- Vue 2 :没有
watchEffect,需使用watch配合immediate: true模拟类似行为。45 - Vue 3 :引入
watchEffect,它会立即执行一次并自动追踪依赖,无需指定监听源。但watchEffect无法获取变化前的值(oldVal),而watch可以。34- 适用场景:
watch:需要区分新旧值或精细控制监听源时。watchEffect:依赖较多且只需执行副作用(如 API 调用)时,代码更简洁。4
- 适用场景:
5. 性能优化与最佳实践
- 避免深度监听 :Vue 3 中监听
reactive对象默认深度监听,但建议仅监听必要属性以提升性能。