对象的shallow watch有哪些适用场景及触发条件?
浅监听的触发规则
首先先把触发逻辑说透,避免踩坑:
只有当你监听的是「返回对象的getter函数」(比如watch(() => formState, () => {})),或者显式设置deep: false时,对对象的监听才是浅的(注意:直接把reactive创建的响应式对象传给watch时,Vue会默认强制开启深度监听,和你写不写deep配置无关)。
浅监听模式下,只有被监听的对象引用地址发生整体替换时,才会触发回调:
- 不管你修改对象的第一层属性还是深层嵌套属性,只要对象还是原来那个引用,回调永远不会执行
- 只有你给这个变量重新赋了一个全新的对象(比如
formState = { name: '', age: 0 }、userInfo = await fetchUserInfo()),新旧引用不一致的时候,回调才会跑
典型适用场景
浅监听最大的优势是性能极高——不需要递归遍历对象的所有属性挂载依赖,对大对象、复杂结构对象非常友好,常见适用场景都是只关心对象整体替换、不关心内部属性变动的情况:
- 表单/配置项的重置、回填场景。比如做复杂表单时,点重置会直接给表单对象赋初始值的新副本,编辑回填会直接把接口返回的新对象整个赋值给表单变量,这时候你只需要在整个表单被替换时做一次性初始化(比如清空校验提示、重置关联选项状态),不需要响应单个输入框修改带来的属性变化,用浅监听比深监听省很多性能开销。
- 第三方实例的生命周期监听。比如初始化ECharts、富文本编辑器、地图SDK这类返回大实例对象的场景,实例内部会频繁更新属性触发变动,你完全不需要关心它内部改了什么,只需要在实例被重建、销毁(引用从实例变成null,或者换成新实例)的时候做处理(比如重新绑定事件、回收旧实例内存),这时候开深监听不仅浪费性能,甚至可能因为实例内部的循环引用导致栈溢出。
- 全局状态的存在性判断。比如监听全局存的用户信息对象,你只需要关心用户从未登录(对象为null)切到已登录(对象为用户信息)、或者从普通用户切到管理员账号这类整体身份切换的场景,用户昵称、头像这类单个属性的变动有单独的监听逻辑处理,不需要在这个全局回调里执行,用浅监听就完全够用。
踩坑提醒:别把浅监听当成「只监听对象第一层属性」,浅监听根本不追踪对象内部任何属性的变化,它只认引用地址。如果只需要监听对象某几个特定属性,直接把对应属性单独作为
watch的源即可,性能比开深度监听好得多。
内容的提问来源于stack exchange,提问作者WoJ
相关产品推荐
相关产品推荐

