同时配置 deep: true 和 immediate: true 是解决“初始化执行+深层响应”需求的标准做法:前者递归监听嵌套属性,后者使回调在组件创建时立即执行一次,二者结合实现逻辑闭环。

可以同时配置 deep: true 和 immediate: true,这是解决“初始化就要执行 + 内部任意变化都要响应”这类需求的标准做法。
Vue 2 选项式 API 写法
在组件的 watch 选项中,以对象形式声明监听器,并把两个配置都写进去:
- 监听目标是响应式数据(如
data中定义的userInfo) -
handler是回调函数,接收新值和旧值 -
deep: true启用递归监听嵌套属性 -
immediate: true让 handler 在组件创建时立刻执行一次
示例:
watch: {
userInfo: {
handler(newVal, oldVal) {
console.log('userInfo 变了(含内部字段)', newVal)
// 注意:首次执行时 oldVal 是 undefined
if (oldVal === undefined) {
console.log('这是初始化触发')
}
},
deep: true,
immediate: true
}
}
Vue 3 组合式 API 写法
使用 watch() 函数,第三个参数传入配置对象:
- 第一个参数是监听源,必须是 getter 函数(如
() => userInfo),不能直接写userInfo - 第二个参数是回调函数
- 第三个参数为配置对象:
{ deep: true, immediate: true }
示例:
import { watch, reactive } from 'vue'
const userInfo = reactive({
name: '张三',
profile: { avatar: '/avatar.png' }
})
watch(
() => userInfo,
(newVal, oldVal) => {
console.log('userInfo 深度变化或初始化', newVal)
// 首次调用时 oldVal 为 undefined
},
{ deep: true, immediate: true }
)
为什么必须组合用?单独用会怎样?
只设 immediate: true:初始化能执行,但改 userInfo.profile.avatar 这类深层字段时不会触发。
只设 deep: true:深层字段修改能捕获,但组件一上来不会自动执行,得等第一次变化才动。
两者一起:初始化执行一次(oldVal 为 undefined),之后每次任何嵌套属性变化都再触发 —— 逻辑闭环,不用额外在 created 或 onMounted 里重复写初始化逻辑。
注意事项
- 回调中务必判断
oldVal === undefined,避免对未定义值做操作(比如oldVal.length报错) - 性能敏感场景慎用
deep: true,尤其监听大对象或频繁更新的对象;优先考虑监听具体路径(如() => user.profile.name) - 监听非响应式对象(如通过
Object.assign替换整个对象)时,deep无效,需确保源头是reactive或ref


















