ref对象必须通过.value访问和修改,直接赋新对象或解构会丢失响应式;正确做法是user.value.name='张三'或user.value={name:'李四',age:25}。

ref 里存对象,修改时必须通过 .value 访问再操作属性,不能直接赋新对象;否则响应式会断掉。这是最常踩的坑。
ref 对象的正确修改方式
ref 包裹对象后,它内部仍靠 reactive 深度转为响应式,但外层是 ref 实例,所以所有读写都得走 .value。
- ✅ 正确:修改属性
user.value.name = '张三'或user.value.age++ - ✅ 正确:替换整个对象(保留 ref 引用)
user.value = { name: '李四', age: 25 } - ❌ 错误:直接赋值
user = { name: '王五' }—— 这会让 user 变成普通变量,丢失响应式 - ❌ 错误:解构后修改
const { name } = user; name = '赵六'—— 解构破坏响应链,模板不会更新
嵌套对象和数组的更新要点
如果 ref.value 是对象或数组,它的子属性天然响应式,但要注意“替换”和“修改”的区别:
- 数组清空重填:用
list.value = newDataArray,别写list = newDataArray - 对象新增字段:直接
obj.value.newKey = 'val',Vue 3 支持响应式新增 - 深层嵌套修改:比如
form.value.profile.address.city = '杭州',无需额外操作,Proxy 自动追踪
配合 Store 使用时的实用技巧
在 Pinia 或自定义 store 中用 ref 管理局部状态时,推荐以下写法保持清晰和可维护:
- 把 ref 当作“带壳容器”,只在 setup 或 composition 函数内通过
.value操作 - 对外暴露时,可用
toRefs解包(适合返回多个顶层响应式字段):return { ...toRefs(store) } - 需要传给子组件或函数又怕丢失响应性?传
store本身,而不是store.value.xxx—— 后者是普通值 - 调试时快速确认:
console.log(isReactive(store.value))应为 true
不复杂但容易忽略:ref 的核心就一条——外层壳不变,里面的内容可换可改;换壳就失效。

















