ref 用 object.defineproperty 劫持 .value,基本类型响应、引用类型转 reactive;reactive 全程 proxy,立即深度代理,支持动态属性;ref 可替换值,reactive 需原地修改;解构后 ref 依赖 .value,reactive 需 torefs。

Vue 3 中 ref 和 reactive 的底层实现差异,直接决定了它们的使用边界和行为表现。理解这些区别,不是为了背原理,而是避免踩坑——比如为什么 reactive 不能包数字、为什么 ref 解构后还能用但 reactive 不行。
响应式劫持机制不同
ref 对基本类型(number/string/boolean)采用 Object.defineProperty 劫持其 .value 属性的 getter/setter,实现依赖收集与触发更新;对引用类型(对象/数组),ref 内部会自动调用 reactive,转为 Proxy 代理。
reactive 则全程基于 ES6 Proxy,直接代理整个目标对象,拦截 get/set/deleteProperty/has/ownKeys 等操作,天然支持深层嵌套响应、动态属性增删。
响应式层级与递归逻辑不同
- ref 是“一层包装 + 按需递归”:它本身只让 .value 这个属性响应,当 .value 是对象时,才启动 reactive 做深度代理;若 .value 是普通对象未被访问,内部属性不会提前响应化
- reactive 是“立即深度代理”:创建时即递归遍历所有可枚举属性,对嵌套的对象、数组、Map/Set 全部应用 Proxy,确保任意层级修改都能触发更新
值的可替换性与引用稳定性不同
- ref 返回的是一个固定引用的对象(如 { value: 42 }),你可以随时执行
count.value = 100或count.value = { name: 'Alice' },引用本身不变,响应式连接始终有效 - reactive 返回的是原对象的代理,一旦你写
state = { count: 99 },就等于丢弃了原来的 Proxy,新对象完全不响应;必须用Object.assign(state, { count: 99 })或逐个赋值来维持响应性
解构后的响应式保持方式不同
两者解构都会丢失响应性,但修复路径不同:
- 对 ref 解构出的变量(如
const { value: countVal } = count),仍需通过countVal访问,但已脱离响应式系统——真正安全的解构是配合toRefs或保持用.value - reactive 解构后(如
const { count } = state)得到的是普通值,必须用toRefs(state)转成一组 ref,才能在模板或 script 中继续响应式使用
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










