在 Vue 3 中,watch 默认惰性执行,启用 immediate: true 可使其在组件初始化时同步执行一次回调,此时 newVal 为当前值、oldVal 为 undefined。

在 Vue 3 中,想让 watch 在组件初始化时就执行一次回调,而不是等数据变化才触发,关键就是启用 immediate: true 选项。
immediate 的作用和默认行为
默认情况下,watch 是“惰性”的——它只在监听的数据真正发生变化后才运行回调。这意味着初始值不会触发任何逻辑,哪怕你已经设置了数据。
加上 { immediate: true } 后,Vue 会在组件 setup 阶段、DOM 渲染前,**同步调用一次回调函数**,传入当前数据的最新值(newVal),而 oldVal 此时为 undefined。
基础写法:监听 ref 并立即执行
这是最常见也最直观的用法:
立即学习“前端免费学习笔记(深入)”;
审查 Vue 管理后台的变更请求(Vue 2 + Element UI,Vue 3 + Element Plus)。重点关注最小化变更实现、上线风险检查以及回归检查清单生成。
- 直接把
ref变量作为监听源 - 回调接收
(newVal, oldVal),首次调用时oldVal是undefined - 配置对象中加入
immediate: true
示例:
<script setup>import { ref, watch } from 'vue'
const searchQuery = ref('')
watch(searchQuery, (newVal, oldVal) => {
console.log('搜索关键词:', newVal)
if (newVal) fetchResults(newVal)
}, { immediate: true })
</script>
监听 reactive 对象的属性时怎么用
如果你监听的是 reactive 对象里的某个字段(比如 user.name 或 form.items),不能直接传对象属性,必须用 getter 函数包装:
- 监听源写成
() => state.user.name,确保响应式依赖被正确收集 - 仍可加
{ immediate: true },首次执行时拿到的就是初始化的name值 - 如果该属性是嵌套结构且可能深层变动,再叠加
deep: true
示例:
const state = reactive({user: { name: 'Tom', profile: { city: 'Shanghai' } }
})
watch(() => state.user.name, (newName) => {
console.log('用户名已设为:', newName)
}, { immediate: true })
注意事项和常见坑
使用 immediate 时要注意几个实际细节:
-
oldVal第一次总是undefined,判断逻辑里别直接用oldVal === null或做严格相等比较 - 如果监听的是整个
reactive对象(如watch(user, ...)),Vue 3 默认会深度响应,但oldVal和newVal指向同一引用,无法获取真正“旧”的快照 - 避免在高频创建/销毁的组件(如列表项)中滥用
immediate,否则可能带来不必要的初始化开销 - 与
watchEffect不同,watch+immediate能明确区分新旧值,更适合需要对比或仅响应变更的场景

















