vue 3 中 ref 通过内部 reactive 实现深层响应式,.value 指向 reactive 实例,嵌套属性访问时自动递归代理;watch ref 对象即可监听所有已访问的嵌套变化,无需 deep: true。

Vue 3 中 ref 本身不直接“实现”深层监听,而是通过内部封装 reactive 来天然支持嵌套对象的响应式更新。关键在于:ref 包裹的对象,其 .value 属性指向一个 reactive 实例,所有嵌套层级都由 Proxy 逐层接管,无需额外配置。
ref 的深层响应靠的是 reactive 底层支撑
当你写 ref({ a: { b: 1 } }),Vue 实际创建的是:
- 一个 ref 对象,其
.value指向一个reactive({ a: { b: 1 } }) - 而这个
reactive又对a执行懒递归代理——首次访问.value.a时,自动用reactive包装{ b: 1 } - 再访问
.value.a.b,同样触发代理,最终整个结构形成多层 Proxy 链
watch ref 时无需 deep: true,但要注意写法
监听 ref 类型的嵌套数据,直接传 ref 对象即可,Vue 会自动解包并追踪所有已访问的嵌套属性:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- ✅ 正确:
watch(user, (newVal) => {...}),其中user = ref({ profile: { name: 'Alice' } }) - ✅ 修改
user.value.profile.name = 'Bob'会触发回调 - ❌ 错误:
watch(user.value, ...)—— 传的是解包后的普通对象,失去响应性连接
什么时候深层响应会“断掉”?
不是所有嵌套都能被代理,以下情况会终止递归:
- 基础类型(
string/number/null等)和内置对象(Date、Map、RegExp)不被代理,只保留原值 - 使用
shallowRef或shallowReactive会显式切断递归,例如shallowRef({ x: { y: 1 } }).value.x.y = 2不触发更新 - 手动替换整个
.value(如user.value = { profile: { name: 'New' } }),新对象需重新访问属性才能建立响应链
对比 Vue 2 的 deep: true 更可靠
Vue 3 的深层响应是数据初始化时就确立的代理关系,不是运行时遍历模拟:
- 支持新增属性:
user.value.profile.age = 25视图立即更新 - 支持数组索引赋值:
list.value[0] = { id: 1 }能被侦听到 - 所有响应式操作(
push、splice、length = 0)全部原生生效,无需Vue.set
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









