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

Vue3 Composition API 状态管理避坑实录

tenfei
tenfei
发布于2026-08-10 11:45 阅读5次
Vue3 Composition API 状态管理避坑实录
记录 Vue3 从 Options API 迁移到 Composition API 过程中遇到的响应式丢失、ref 自动解包陷阱、watch 监听失效等实际问题,通过真实组件重构案例逐一剖析原因与解决方案,附带 Pinia 最佳实践建议。
# Vue3 Composition API 状态管理避坑实录 ## 背景 Vue3 发布至今,Composition API 已成为官方推荐的编码范式。相比 Options API,它在逻辑复用和类型推导上有明显优势。但在实际项目迁移中,不少开发者踩过响应式相关的坑。本文整理了几个高频问题。 ## 坑1:reactive 解构后丢失响应式 最经典的陷阱。用 reactive() 包裹对象后,一旦解构赋值,响应式就断了。 ```javascript import { reactive } from 'vue'; const state = reactive({ count: 0, name: 'Vue' }); // 错误:解构后 count 和 name 变成普通值 const { count, name } = state; count++; // 不会触发更新! // 正确:用 toRefs 转为 ref 引用 import { toRefs } from 'vue'; const { count, name } = toRefs(state); count.value++; // ok,模板中可以省略 .value ``` 原因:reactive() 返回的是 Proxy 对象,解构相当于取出原始值的副本,脱离了 Proxy 的拦截。 ## 坑2:ref 在 reactive 中的自动解包 ```javascript const count = ref(0); const state = reactive({ count }); state.count++; // 自动解包,不需要 .value console.log(state.count); // 1 // 但是! const arr = reactive([ref(0)]); console.log(arr[0]); // 不解包!返回 RefImpl 对象 arr[0]++; // 不会更新视图 // 数组、Map、Set 等集合类型中 ref 不会自动解包 // 必须 .value:arr[0].value++ ``` 规律:ref 在 reactive 的普通对象属性中自动解包,但在数组、Map、Set 等集合类型中不解包。 ## 坑3:watch 监听 reactive 对象的属性值 ```javascript const state = reactive({ count: 0 }); // 错误:直接监听属性值,拿到的是快照 watch(state.count, (val) => console.log(val)); // 正确:使用 getter 函数 watch(() => state.count, (val) => console.log(val)); // 或者用 watchEffect(自动追踪依赖) watchEffect(() => console.log(state.count)); ``` ## 坑4:computed 中的异步操作 ```javascript // computed 不支持异步! const data = computed(async () => { const res = await fetch('/api/data'); return res.json(); // 返回的是 Promise,不是数据 }); // data.value 是一个 Promise,模板中无法直接渲染 // 用 ref + watchEffect const data = ref(null); watchEffect(async () => { data.value = await fetch('/api/data').then(r => r.json()); }); ``` ## 推荐方案:Pinia Setup Store ```javascript import { defineStore } from 'pinia'; import { ref, computed } from 'vue'; export const useUserStore = defineStore('user', () => { const token = ref(''); const profile = ref(null); const isLoggedIn = computed(() => !!token.value); async function login(creds) { const res = await apiLogin(creds); token.value = res.token; profile.value = res.profile; } function logout() { token.value = ''; profile.value = null; } return { token, profile, isLoggedIn, login, logout }; }); ``` Setup Store 的写法让 Composition API 的经验可以直接复用到状态管理中。 ## 总结 | 问题 | 原因 | 解决 | |------|------|------| | reactive 解构失效 | 脱离 Proxy | 用 toRefs | | 数组中 ref 不解包 | 集合类型特殊性 | 手动 .value | | watch 监听属性值 | getter 才能追踪 | 用 () => x.attr | | computed 异步 | 设计不支持 | ref + watchEffect | 掌握这些要点,Vue3 响应式体系就能得心应手了。

2

0

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