Vue 3 中的侦听器通过 watch 和 watchEffect 函数实现,用于监听响应式数据的变化,并在变化发生时执行回调函数。这些工具提供了精确的数据追踪和处理机制,支持深度监听对象或数组属性的变化,以及对监听选项进行细粒度控制,有助于实现复杂的数据依赖逻辑与副作用管理。
watch 是 Vue 3 核心侦听 API,用于显式监听指定的响应式数据源,数据变化时执行回调。它支持获取新值、旧值,可控性更强,是 Vue 3 最常用的侦听方式。
源(source):必填,监听的目标,可以是 ref / reactive 对象、对象属性、返回值的 getter 函数、数据源数组。
回调函数(callback):必填,数据源变化时执行,接收 新值、旧值 两个参数。
选项(options):可选,配置侦听行为:
immediate:布尔值,true 表示组件初始化时立即执行一次回调。
deep:布尔值,true 表示开启深度监听,监听嵌套对象 / 数组的内部变化。
flush:控制回调执行时机,默认 pre(组件更新前),可选 post(DOM 更新后)、sync(同步执行,极少使用)。
onTrack / onTrigger:调试用,追踪响应式依赖的触发逻辑。
<template>
<button @click="count++">count + 1</button>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const count = ref(0);
// 监听基础数据类型
watch(count, (newValue, oldValue) => {
console.log(`count 从 ${oldValue} 变为 ${newValue}`);
});
</script>监听 reactive 对象时,无需配置 deep: true,会自动深度监听。
<script setup lang="ts">
import { reactive, watch } from 'vue';
const user = reactive({ name: 'Tom', age: 18 });
// 自动深度监听,无需 deep
watch(user, (newVal) => {
console.log('用户信息更新:', newVal);
});
</script>精准监听对象属性,避免不必要的触发,使用 getter 函数 声明源。
<script setup lang="ts">
import { reactive, watch } from 'vue';
const user = reactive({ name: 'Tom', age: 18 });
// 仅监听 name 属性
watch(() => user.name, (newVal) => {
console.log('姓名更新:', newVal);
});
</script>可同时监听多个数据,回调参数为数组格式。
<script setup lang="ts">
import { ref, watch } from 'vue';
const name = ref('Tom');
const age = ref(18);
watch([name, age], ([newName, newAge], [oldName, oldAge]) => {
console.log(`姓名:${oldName} → ${newName},年龄:${oldAge} → ${newAge}`);
});
</script>ref 包裹的对象 / 数组,需要手动配置 deep: true 开启深度监听。
<script setup lang="ts">
import { ref, watch } from 'vue';
const userProfile = ref({ name: 'John Doe', age: 30 });
watch(
userProfile,
(newProfile) => console.log('资料更新'),
{ deep: true } // 必须开启深度监听
);
</script>配置 immediate: true,组件初始化时自动执行一次回调。
watch(count, () => console.log('初始化/数据变化'), { immediate: true });watch 会返回一个停止函数,调用后可手动终止侦听。
const stopWatch = watch(count, () => {});
// 停止侦听
stopWatch();watchEffect 是自动追踪依赖的副作用侦听器,无需手动指定监听源,回调中使用的响应式数据会被自动监听,初始化立即执行。
自动依赖追踪:回调内使用的响应式数据,变化后自动重新执行。
立即执行:组件初始化时默认执行一次,无需配置 immediate。
无新值旧值:专注于执行副作用逻辑,不关注值的变化细节。
副作用清理:内置清理函数,可清除定时器、取消请求等。
<template>
<button @click="count++">count + 1</button>
</template>
<script setup lang="ts">
import { ref, watchEffect } from 'vue';
const count = ref(0);
// 自动追踪 count,初始化执行 + 变化后执行
watchEffect(() => {
console.log(`Count is: ${count.value}`);
});
</script>用于清理定时器、取消网络请求、解绑事件,避免内存泄漏。
<script setup lang="ts">
import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect((onInvalidate) => {
// 开启定时器
const timer = setInterval(() => console.log(count.value), 1000);
// 清理函数:下次执行前 / 组件卸载时自动调用
onInvalidate(() => clearInterval(timer));
});
</script>通过 flush 控制执行时机,用法与 watch 一致。
// DOM 更新完成后执行
watchEffect(() => {}, { flush: 'post' });监听数据变化后发送异步请求(如搜索、表单提交);
需要获取新值、旧值做对比逻辑;
精准监听单个 / 多个指定数据源,避免不必要的触发。
简单的数据联动逻辑(如表单验证、状态同步);
需要自动清理副作用(定时器、请求、事件);
无需关心数据源,只关注执行副作用的场景。
组件卸载时,Vue 会自动停止侦听器,无需手动清理;
优先精准监听,避免滥用深度监听,提升性能;
异步操作优先在 watch 中处理,逻辑更清晰。
watch:显式监听、可控性强,支持新值旧值,适合复杂业务逻辑;
watchEffect:自动追踪、开箱即用,适合简单副作用处理;
核心配置:immediate(立即执行)、deep(深度监听)、flush(执行时机);
必备能力:清理副作用、停止侦听,是避免内存泄漏的关键。