Vue组合式函数用useFetch为何不隔离?Nuxt3场景BUG求助
问题:Nuxt3组合式函数中useFetch请求结果相互覆盖
技术栈与场景
使用Vue 3 + Nuxt 3 + Vite开发项目,编写了useCheckerRole组合式函数用于根据用户角色判断组件是否可渲染:
useCheckerRole 组合式函数
export function useCheckerRole(policies){ const {data, error} = await useFetch("/api/role-checker", { method: "POST", body: policies }) if(data.value) { return data.value } if(error.value) { throw new Error("an error occured"); } }
调用方式
const policies = await useCheckerRole([ { component_ask: 'some-button', role_ask: 'administrator' } ])
接口返回示例
[{ component_ask: 'some-button', role_ask: 'administrator', status: 'approved' }]
BUG表现
同一页面的两个组件同时调用useCheckerRole时,请求结果相互覆盖:
- TopBar.vue传入自身规则,却拿到了ChildPage.vue的请求结果
- ChildPage.vue结果正常,TopBar的结果被覆盖
TopBar.vue代码
const policies = await useCheckerRole([ { component_ask: 'top-bar-button', role_ask: 'administrator' } ]).catch((error) => { /* 错误处理 */ }) console.log("topBar Policies result", policies)
ChildPage.vue代码
const policies = await useCheckerRole([ { component_ask: 'child-page-button', role_ask: 'administrator' }, { component_ask: 'child-page-other-button', role_ask: 'administrator' }, ]).catch((error) => { /* 错误处理 */ }) console.log("Child Policies result", policies)
实际结果与预期
- TopBar实际拿到的结果(和ChildPage一致):
[ { component_ask: 'child-page-button', role_ask: 'administrator', status: "approved" }, { component_ask: 'child-page-other-button', role_ask: 'administrator', status: "rejected" }, ]
- TopBar应得的结果:
[ { component_ask: 'top-bar-button', role_ask: 'administrator', status: "approved" }, ]
解决方案
问题原因
Nuxt的useFetch默认仅根据请求URL生成缓存键,POST请求的请求体(body)不会被纳入缓存键计算逻辑。这导致两个不同body但相同URL的POST请求会共享同一个缓存,后发起的请求结果会覆盖先发起的。
修复方法
给每个useFetch请求添加唯一缓存键,基于传入的policies生成,确保不同请求的缓存相互隔离。
修改后的useCheckerRole函数:
export function useCheckerRole(policies){ // 基于请求体生成唯一缓存键,避免不同请求共享缓存 const fetchKey = JSON.stringify(policies) const {data, error} = await useFetch("/api/role-checker", { method: "POST", body: policies, key: fetchKey // 显式指定唯一缓存键 }) if(data.value) { return data.value } if(error.value) { throw new Error("权限校验请求出错"); } }
补充说明
- 使用
JSON.stringify(policies)生成键,能确保只要policies内容不同,缓存键就不同,彻底避免冲突 - 这种方式既解决了覆盖问题,又保留了相同
policies请求的缓存复用能力,减少重复请求 - 如果完全不需要缓存,也可以设置
cache: false,但不推荐,缓存能有效提升页面性能
内容的提问来源于stack exchange,提问作者Egy Ramschie
相关产品推荐
相关产品推荐

