Vuex Getter返回代理对象无法通过公共getter读取类私有字段怎么办
问题原因
ES 规范中类的私有字段(#开头的字段)存在严格的实例身份校验:仅当访问时的this指向原始类实例本身时,才能正常读取私有字段。
VueX 返回的对象经过 Vue 响应式系统的Proxy代理包装,你调用公共getter时,函数内部的this指向的是代理对象,而非原始的Example类实例,因此触发私有字段校验失败,抛出错误:
TypeError: attempted to get private field on non-instance
解决方案
以下方案均不需要修改私有字段为公共字段:
方案1:存储到VueX时标记实例为非响应式
存入VueX前用markRaw包裹类实例,让响应式系统跳过对该实例的代理包装,取出时直接拿到原始实例。
示例代码:import { markRaw } from 'vue' // 存入VueX的逻辑示例 const exampleInstance = new Example() store.commit('saveExampleList', [markRaw(exampleInstance)])注意:该方案下实例不会具备响应式能力,适合存入后不需要变更、仅做读取的类实例。
方案2:读取时从代理还原原始实例
用Vue官方提供的toRawAPI,直接从Proxy代理对象中获取原始实例,再访问私有字段即可。
示例代码:import { toRaw } from 'vue' computed(){ getInfoForSpecificItem() { const arrayOfInstantiatedExamples = this.$store.getters['getArrayOfInstantiatedExamples']; for (let i = 0; i < arrayOfInstantiatedExamples.length; i += 1) { // 先还原原始实例再访问 const rawItem = toRaw(arrayOfInstantiatedExamples[i]) if (rawItem.privateField === 'something') { // 执行业务逻辑 } } } }方案3:类定义阶段绑定getter的this指向
在类的构造函数中,将公共getter的this硬绑定到原始实例,后续无论调用者是代理对象还是其他上下文,getter内部的this始终指向原始实例,可正常访问私有字段。
示例代码:class Example { #privateField; constructor() { // 绑定getter的this到原始实例 this.privateField = this.privateField.bind(this) } get privateField() { return this.#privateField; } }该方案不影响实例的响应式能力,适合需要响应式更新的类实例场景。
内容的提问来源于stack exchange,提问作者D.Schaller
相关产品推荐
相关产品推荐

