你的浏览器无法正常显示内容,请更换或升级浏览器!

Vue3 项目踩坑笔记:响应式丢失的六个真实场景

tenfei
tenfei
发布于2026-09-11 10:08 阅读15次
Vue3 项目踩坑笔记:响应式丢失的六个真实场景
用 Vue3 组合式 API 写页面,最头疼的就是数据改了视图不更新。本文汇总我在真实项目中遇到的六个"响应式丢失"场景:解构 reactive、ref 忘记 .value、数组下标赋值、props 直接改、异步里丢引用、以及 shallowRef 的误用,每个都给出原因和正确写法。
# 一、响应式不是万能的 Vue3 的响应式基于 Proxy,比 Vue2 的 defineProperty 强很多,但**仍有明确的失效边界**。下面六个场景我都在项目里真实踩过,改完之后页面终于正常刷新。 # 二、六个真实场景 ## 1. 解构 reactive 对象 ```js const state = reactive({ count: 0 }) const { count } = state // 解构后失去响应式 ``` 解构出来的是普通值。正确做法用 `toRefs`: ```js const { count } = toRefs(state) // 保持响应式 ``` ## 2. ref 在 script 里忘记 .value 模板里自动解包,但 `<script setup>` 里必须 `.value`。这个坑最容易在 `if (loading)` 这种判断里出现——**空对象 truthy**,逻辑永远走错分支。 ## 3. 直接给数组下标赋值 `arr[0] = x` 在 Vue3 里其实是响应式的(Proxy 覆盖到了),但如果数组来自 `Object.freeze` 或 props 传入的只读数组,就不会更新。用 `splice` 更稳妥。 ## 4. 直接修改 props ```js props.list.push(item) // 子组件改父数据,反模式 ``` 要么 emit 事件让父组件改,要么在子组件里用 `const local = ref([...props.list])` 建立本地副本。 ## 5. 异步回调里丢了引用 在 setTimeout / Promise 里拿到的是**旧的解构值**,即使原对象变了也不会触发。解决办法:回调里始终通过对象访问 `state.xxx`,而不是提前解构。 ## 6. shallowRef 误用 `shallowRef` 只监听 `.value` 整体替换,内部属性变化不触发。适合存大型只读数据,但如果当成 `ref` 用来改内部字段,就会"改了不动"。 # 三、通用排查套路 1. 先确认数据源类型:ref / reactive / props / 普通值; 2. 打开 Vue DevTools 看数据面板,**值变了但视图没动**基本就是响应式断裂; 3. 优先用 `toRefs`、`computed`、`watch` 这些官方 API,少走非响应式的捷径。 # 四、小结 Vue3 的响应式失效几乎都源于"数据经过了非响应式的中间层"——解构、赋值、冻结、浅层代理。记住这句话,九成这类 bug 都能秒定位。

1

0

文章点评
赞助商广告位
Copyright © from 2021 by namoer.com
458815@qq.com QQ:458815
蜀ICP备2022020274号-2