Vue 2 和 Vue 3 中的 watch 机制在核心功能上相似,但语法、灵活性和底层实现有显著差异。以下是主要区别的详细对比:
1. 基本用法与语法
-
Vue 2:
watch是一个选项(option),通常作为组件配置对象中的一个属性。它是一个对象,键是需要监听的数据表达式,值是回调函数或包含选项的对象。-
例如:
-
<template>
<div>
count: <input v-model="count" />
name: <input v-model="user.name" />
<br />
<button @click="count++">+</button>
<button @click="decrementCount">-</button>
<button @click="resetUser">Reset User</button>
</div>
</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>
- Vue 3:
watch是一个函数,需要从vue库中导入。它更灵活,支持监听ref、reactive对象、getter 函数等多种数据源。 - 例如:
<template>
<div>
count: <input v-model="count" />
name: <input v-model="user.name" />
<br />
<button @click="count++">+</button>
<button @click="changUser">修改user</button>
</div>
</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}`);
});
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函数清理副作用(如取消定时器或网络请求),避免内存泄漏。
- Vue 3 的
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对象默认深度监听,但建议仅监听必要属性以提升性能。
758

被折叠的 条评论
为什么被折叠?



