Pinia Store问题:Proxy导致Set对象方法在Actions中无法访问
Pinia Store问题:Proxy导致Set对象方法在Actions中无法访问
嘿,我之前也踩过这个Pinia的小坑!你遇到的has is not a function报错,本质是因为Pinia会用Vue的Proxy把整个state包裹起来做响应式处理,你直接通过this.abilities拿到的不是原始的Set实例,而是被代理后的对象,自然没法调用Set原生的方法。
给你几个实用的解决方案,你可以根据自己的场景选:
方案一:用toRaw取出原始Set实例
这是最直接的办法,Vue提供了toRaw方法可以从Proxy中提取出原始对象。
首先在store文件里导入toRaw:
import { toRaw } from 'vue'
然后修改你的actions方法:
allows(ability: string) { if (!this.user) { return false; } // 获取原始的Set对象 const rawAbilities = toRaw(this.abilities) return rawAbilities.has(ability); }, async getAbilities() { if (!this.user) { return } let abilities = [ { code: 'indexSettings', allowed: true } ] // 实际从API获取 // 同样如果要修改Set,也建议先取原始对象操作 const rawAbilities = toRaw(this.abilities) await Promise.all( abilities.map(async (ability) => { if (ability.allowed) { rawAbilities.add(ability.code) } }) ) }
方案二:改用数组存储abilities(适合小数据量场景)
如果不想引入toRaw,可以把state里的Set换成普通数组,在需要判断的时候临时转换成Set:
修改state定义:
state: () => { return { user: null as User, abilities: [] as string[], } },
然后调整actions:
allows(ability: string) { if (!this.user) { return false; } return new Set(this.abilities).has(ability); }, async getAbilities() { if (!this.user) { return } let abilities = [ { code: 'indexSettings', allowed: true } ] this.abilities = abilities.filter(item => item.allowed).map(item => item.code) }
这个方法的缺点是每次判断都要创建新的Set,数据量大的话会有性能损耗,适合小体量的权限列表。
方案三:通过Getter封装原始Set
你也可以在store的getter里提前处理好原始Set,之后在actions里直接调用getter:
定义getter:
import { toRaw } from 'vue' // ... getters: { rawAbilities(state) { return toRaw(state.abilities) } }
然后在actions里使用:
allows(ability: string) { if (!this.user) { return false; } return this.rawAbilities.has(ability); },
这种方式可以让代码更整洁,多个actions需要用到Set方法时不用重复写toRaw。
总结一下,核心问题就是Pinia的响应式代理对原生集合对象的方法支持有限,只要拿到原始的Set实例就能正常调用所有方法啦~
备注:内容来源于stack exchange,提问作者Jakub Skurčák
相关产品推荐
相关产品推荐

