Vue 3 中 watch 监听 ref 和 reactive 的核心差异在于响应式机制:ref 直接监听实例,基本类型变更即触发,对象需 deep 才响应内部变化;reactive 天然深度响应,直接监听即可捕获任意层级修改,deep 冗余;监听特定属性时,ref 需用 getter(如 () => user.value.name),reactive 可直接访问(如 () => user.name)。

Vue 3 的 watch 监听 ref 和 reactive 的行为差异,核心在于「被监听目标的类型」和「Vue 如何追踪它的变化」。不是写法不同,而是响应式机制本身决定了监听逻辑的天然区别。
ref 直接监听:基础类型无脑监听,对象需显式 deep
ref 本质是包装器(RefImpl),watch(ref) 监听的是整个 ref 实例。Vue 能自动感知 .value 的变更:
- 监听基本类型 ref(如
ref(0)、ref('abc')):值一变就触发,无需任何配置 - 监听对象类型 ref(如
ref({ a: 1, b: { c: 2 } })):默认只响应.value被整体替换(比如obj.value = { a: 2 }),不响应内部属性变化 - 要监听嵌套属性变化,必须加
{ deep: true }—— 因为 ref 包裹的对象虽经 reactive 转换,但监听入口仍是 ref 本身
reactive 直接监听:天然深度响应,无需 deep
reactive 返回的是 Proxy 代理对象,其响应式是深层的。直接 watch(reactiveObj) 就能捕获任意层级属性的修改:
重要:对 React 或 Next.js 代码的任何更改必须先阅读本技能。Vercel 工程团队的 React 与 Next.js 指南,涵盖可视化...
- 修改
obj.a、obj.b.c、obj.list.push()都会触发回调 -
{ deep: true }是冗余的,Vue 会自动深度追踪 - 注意:如果写成
watch(() => reactiveObj, ...)(函数形式),反而需要deep: true,因为这时监听的是函数返回值,Vue 默认浅监听返回值引用
监听特定属性时,ref 要用 getter,reactive 可直接访问
想只关注某个字段(比如用户姓名),写法更直观:
立即学习“前端免费学习笔记(深入)”;
- ref:必须用箭头函数包裹访问路径,
watch(() => user.value.name, ...) - reactive:可直接传属性访问表达式,
watch(() => user.name, ...)(user 是 reactive 对象) - 两者都不需要
deep—— 因为监听的是一个计算值(getter),Vue 会自动追踪其中所有响应式依赖
watchEffect 里 ref 和 reactive 行为一致
watchEffect 不关心数据类型,它靠运行时依赖收集来追踪:
- 无论
count.value还是user.name,只要在 effect 函数体内读取,就会被自动监听 - 修改任一依赖项都会重新执行 effect
- 不需要手动指定
deep,也不区分 ref/reactive —— 它只认“哪些响应式数据被读了”

















