vue 3 的 watch 默认不监听嵌套属性变化,需用 getter 函数配合 deep: true 才能实现深度监听;直接传响应式对象并设 deep: true 无效,且 oldval 不准确;监听具体路径(如 user.profile.email)更高效精准;多个字段可组合为 getter 数组。

Vue 3 的 watch 默认只监听对象的引用变化或顶层属性变动,不会自动追踪嵌套属性(比如 user.profile.name)的修改。要让深层属性变化也能触发回调,必须显式启用深度监听,并注意写法是否正确。
必须配合 getter 函数使用 deep: true
直接传入响应式对象并设 { deep: true } 是无效的——Vue 3 会忽略该配置,且旧值(oldVal)可能不准确。
✅ 正确做法是:用箭头函数包裹数据源,再传入 { deep: true }:
- 监听整个 reactive 对象的任意嵌套变更
watch(() => user, (newVal, oldVal) => {<br> console.log('user 或其任意子属性变了')<br>}, { deep: true })
⚠️ 注意:user 必须是 reactive 创建的对象;若用 ref 包裹对象,需写成 () => user.value。
监听具体路径更推荐(无需 deep)
如果只关心某个固定字段(如 user.profile.email),直接监听该路径即可。这种方式性能更好、逻辑更清晰,还能稳定获取新旧值。
- 精准响应,避免无谓遍历
- oldValue 和 newValue 类型明确,便于做差异判断
watch(() => user.profile.email, (newEmail, oldEmail) => {<br> console.log(`邮箱从 ${oldEmail} 变为 ${newEmail}`)<br>})
监听多个深层字段可组合成数组
当几个关键嵌套属性都需要响应时(例如 user.profile.name 和 user.status),可以把它们统一包装进数组:
- 数组中每个元素都应是 getter 函数
- 回调参数也变为两个数组:[new1, new2] 和 [old1, old2]
watch(<br> [() => user.profile.name, () => user.status],<br> ([newName, newStatus], [oldName, oldStatus]) => {<br> console.log('姓名或状态变了')<br> }<br>)
补充说明:deep 对 ref 对象也适用
如果是 ref({ a: { b: 1 } }) 这类结构,同样需要 deep: true 才能监听到 obj.value.a.b 的变化,但写法仍是:
watch(() => obj.value, callback, { deep: true })
不能写成 watch(obj, callback, { deep: true }) —— 后者在 Vue 3 中不生效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










