Vue中watch默认不深度监听嵌套对象,需设deep: true并监听顶层对象;避免直接替换属性导致响应式丢失;Vue 3推荐watchEffect自动追踪依赖;数组需注意索引操作限制。

Vue 中 watch 默认不会深度监听嵌套对象的内部变化,尤其是当修改的是对象某一层级的属性(比如 obj.a.b = 3)时,浅层监听会失效。要真正响应深度嵌套对象的变更,关键在于正确配置 deep: true,并注意触发响应的写法和限制。
必须开启 deep: true 且监听整个对象
监听嵌套对象时,不能只监听某个中间属性(如 obj.a),而应监听顶层响应式对象本身,并启用深度监听:
- ✅ 正确:监听
obj,设置deep: true - ❌ 错误:监听
obj.a(即使加deep: true也无效,因为obj.a是个普通值或非响应式引用)
示例:
watch(() => obj, (newVal, oldVal) => {console.log('obj 深度变化')
}, { deep: true })
避免直接替换内部属性(响应式丢失风险)
Vue 的响应式系统依赖于属性访问拦截(Proxy 或 Object.defineProperty)。如果用以下方式修改,新属性不会被自动追踪:
-
obj.a = { b: 1 }—— 若a原本不存在,需用Vue.set(Vue 2)或nextTick+ 重新赋值(Vue 3 推荐用reactive配合结构合理初始化) -
obj.a.b.c = 5—— 只要a和b已是响应式对象,这步可以触发更新(但前提是整个链路从一开始就响应式)
建议:初始化时就定义好完整结构,或使用 ref/reactive 包裹整个嵌套对象。
Vue 3 中更推荐用 watchEffect + 依赖显式读取
相比传统 watch,watchEffect 能自动追踪响应式依赖,写法更简洁、不易遗漏层级:
console.log(obj.a?.b?.c); // 自动收集 obj.a.b.c 的依赖
});
只要在回调中「读取」了嵌套路径,就会自动建立响应联系。但注意:可选链(?.)和空值判断不影响依赖收集,前提是路径上每一层都存在且为响应式。
数组嵌套对象也要小心索引操作
监听数组时,deep: true 能捕获 arr[0].name = 'x' 这类修改,但无法响应以下操作:
-
arr.length = 0(应改用arr.splice(0)) -
arr[10] = newItem(越界赋值不触发,需用arr.push()或Vue.set(arr, 10, newItem)) - 直接替换整个数组(
arr = [...newArr])—— 这会触发监听,但要注意是否仍指向原响应式引用

















