响应式丢失的核心是脱离 proxy 或 ref 追踪链:解构 reactive 会断开响应、返回 plain object 无响应、直接赋值替换对象丢失代理、嵌套对象未用 reactive/toref 保持响应。

组合式函数里响应式丢失,核心在于“脱离了 Proxy 或 ref 的追踪链”。不是函数本身有问题,而是数据在传递、解构、赋值过程中被转成了普通值,Vue 再也监听不到变化。
直接解构 reactive 对象,响应式当场断开
在组合式函数中返回一个 reactive 对象很常见,但如果调用方直接解构,就会出问题:
- ❌ 错误写法:
const { count } = useCounter()→count是数字,不是响应式引用 - ✅ 正确做法:
const counter = useCounter(),模板中用{{ counter.count }};或改用toRefs(useCounter())解构
因为 useCounter() 返回的是 reactive 对象,解构只取值、不保留代理关系。必须靠 toRefs 把每个属性转成独立的 ref,才能让解构后的变量仍可响应更新。
返回 plain object 而非响应式包装,等于交出控制权
组合式函数若返回普通对象(比如 return { count: 0, increment() {} }),那它就只是个 JS 对象,和 Vue 响应式系统完全无关。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- ✅ 推荐返回方式:
return reactive({ count: 0 })或return { count: ref(0) } - ⚠️ 注意:如果返回多个
ref,建议统一用toRefs包裹再 return,方便调用方解构使用
异步数据覆盖时替换整个对象,响应式引用被丢弃
组合式函数常封装 API 请求逻辑。如果请求回来后直接 state = response.data,就相当于把原来的 reactive 变量指向了一个新普通对象。
- ❌ 危险操作:
state = await api.getUser() - ✅ 安全做法:
Object.assign(state, await api.getUser())或逐字段赋值:state.id = res.id; state.name = res.name
这样能确保始终操作的是同一个 Proxy 实例,响应式链不断。
嵌套对象未保持响应式,深层修改不触发更新
当组合式函数内部返回一个 reactive 对象,而调用方又从中取出子对象再做操作(如 const profile = user.profile),这个 profile 如果是普通对象,后续修改就不会响应。
- ✅ 确保嵌套结构本身也是 reactive:
user: reactive({ profile: reactive({ ... }) }) - ✅ 更稳妥的做法:用
toRef(user, 'profile')提取响应式引用,避免拷贝 - ⚠️ 不要对子对象再次调用
reactive(),可能破坏原有代理关系
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









