前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Vue watch reactive 默认深度和 ref 区别
VuVue侦听与生命周期

为什么直接 watch reactive 对象默认深监听,而 watch ref 对象的表现不同?

对象内部是否响应式,与当前 watch 入口默认观察到哪一层,是两个不同问题。

前端进阶之旅 · 一题精讲更新于 2026.09.06
Vue#侦听与生命周期
先看核心答案
理解线索

三种入口对应的关注点

  1. 直接对象观察这一个响应式对象内部的变化
  2. 对象 ref观察容器内部 value 的替换,按需深入
  3. 属性 getter持续读取外层属性,能够跟随它指向的新对象

这里描述默认行为;显式 deep 选项和 shallow 等边界会进一步改变观察范围。

核心回答

先记住这个答案

直接把 reactive 对象交给 watch,默认会观察其深层变化;把保存对象的 ref 交给 watch,通常先观察 ref 的 value 是否变化,内部字段变动需要 deep 或具体字段 getter。getter 返回对象时,默认也主要根据返回对象是否变化判断回调。它们可以指向相近数据,却表达不同的观察范围。应按照要监听嵌套修改还是整体替换来选择来源,而不是只看数据是一个对象。

  • 直接 reactive 来源带有默认深层观察行为
  • 对象 ref 的深响应式转换不等于 watch 默认深遍历
  • 返回对象属性的 getter 可以保留对整体替换的观察

不要把响应式转换与监听遍历混在一起

ref({ settings: { level: 1 } }) 中的对象通常也具有深层响应式能力,组件直接读取 level 时可以参与追踪。但 watch 这个 ref 的默认入口并不因此自动等同于遍历整棵对象。只改 settings.level 与把 ref.value 换成新对象,是两种不同变化。

直接 watch(reactiveObject, callback) 则采用默认深层观察,因此内部字段修改也能引起回调。面试时可以先讲“数据能否产生响应式通知”,再讲“这个监听器订阅了哪些读取”,避免用一个深响应式概念解释所有来源形式。

监听当前子对象与跟随子对象替换不同

假设 state.profile 是一个响应式对象,watch(state.profile, callback) 观察的是调用时传入的那个对象。后来把 state.profile 替换为新对象,并不会让监听器凭空知道外层这个属性入口已经换了目标。它与 watch(() => state.profile, callback) 所表达的关系不同。

getter 每次从 state 读取 profile,可以观察这个属性指向的对象是否替换;如果还需要新对象内部变化,可以进一步使用 deep。需要只关心 profile.name 时,直接返回 name 的 getter 往往更准确,也避免观察头像加载状态等无关字段。

选择最小的完整观察范围

对于服务端返回整份不可变快照的结果,监听 ref 的整体替换可能已经足够。对于用户直接编辑的复杂对象,若副作用确实依赖任意字段,则可以采用深层观察,但要了解遍历成本与 oldValue 不会自动克隆的限制。两种模型都可以成立,关键是更新协议与监听方式一致。

验证时应至少覆盖嵌套字段修改、整个对象替换以及旧对象后续仍被修改三类操作。这样能发现监听还停留在旧对象、深度不够或观察范围过宽的问题。默认批量调度可能合并连续变化,因此测试预期也应围绕实际回调时机设计。

回答前,多想一步

容易答错的地方

ref 里的对象不能响应深层修改
普通 ref 通常会对对象进行深层响应式转换,只是 watch 该 ref 的默认观察范围不同。不能把监听器没有回调直接归因于对象完全不响应。
直接监听子对象会永远跟随父属性换新值
监听器拿到的是当时对象,父属性的替换关系需要通过 getter 或稳定容器表达。持有旧对象的引用不会自动变成新对象。
试着用自己的话回答

面试官还会怎么问?

怎样同时观察对象替换和内部字段修改?

可以监听返回该对象属性的 getter,并按需要开启 deep;或者更准确地监听具体字段。应确认深度和数据规模,而不是默认对所有对象全面遍历。

直接 watch reactive 对象时能拿到独立旧快照吗?

不能由默认深监听推导有历史快照。内部原地修改时新旧参数可能是同一个对象,需要独立设计比较或历史记录。

使用 shallowRef 后 deep 能自动补回所有能力吗?

不能把 deep 当成把任意普通内部对象变成深响应式的开关。浅层容器有明确的通知边界,内部非响应式写入不会凭空产生通知,通常应按整体替换等约定更新。

从一道题,走向一组知识

把知识连起来

侦听与生命周期

Vue watch 监听 ref、reactive 对象和 getter 时有什么区别?

先按来源形式理解 watch 接收的入口,再决定观察范围。

侦听与生命周期

Vue watch 开启 deep 会发生什么,为什么可能增加性能成本?

确实需要嵌套变化时,继续评估 deep 的成本与版本边界。

参考资料

  • Reactivity API: watch
  • Watchers: Deep Watchers
  • Reactivity API: Advanced

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 不要把响应式转换与监听遍历混在一起
  3. 监听当前子对象与跟随子对象替换不同
  4. 选择最小的完整观察范围
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑