Pinia(Vue3)如何编写getter访问state深层对象内的数组
Pinia嵌套State的Getter编写方案
问题复现
在Pinia(base.js)中定义Store代码如下:
export const useBaseStore = defineStore('base', { state: () => { return { areaLocal: [ { id: 0, name: 'LAX' }, { id: 1, name: 'SFO' }, { id: 2, name: 'SAN' }, ], areaLocal2: { area: [ { id: 0, name: 'AAA' }, { id: 1, name: 'BBB' }, { id: 2, name: 'CCC' }, ] }, } }, getters: { getAreaById: (state) => { return (areaId) => state.areaLocal.find((areaLocal) => areaLocal.id === areaId) }, // ... } })
在Vue组件(area.vue)中实现代码如下:
<script setup> import { computed, ref } from 'vue' import { storeToRefs } from 'pinia' import { useBaseStore } from '../stores/base' const areaStore = useBaseStore() const { getAreaById } = storeToRefs(areaStore) const areaIndex = ref(0) </script> <template> <div class="container"> <h2>AREA: {{ getAreaById(areaIndex).name }}</h2> <!-- 其余业务代码 --> </div> </template>
当前访问state根层级的areaLocal数组时,可正常获取到AREA: LAX的预期结果。现需要编写对应getter访问嵌套在areaLocal2对象下area字段的数组,尝试编写的查询逻辑如下:
state.areaLocal2.area.find((areaLocal2.area) => areaLocal.id.area === areaId
上述代码运行时抛出undefined错误。
错误原因
原有写法存在三个明显问题:
Array.find方法的回调函数参数必须是合法的变量名,不能写对象路径格式的areaLocal2.area,该参数代表遍历过程中当前命中的数组元素areaLocal2.area下的数组元素结构为{id: number, name: string},不存在id.area这个嵌套属性,直接读取元素的id字段和传入的areaId比对即可- 整行代码缺少闭合括号,本身存在语法错误
正确实现
1. 编写对应Getter
在Store的getters字段中新增方法,和原有根层级数组的查询逻辑保持一致,先定位到嵌套的数组路径再调用find即可:
getters: { getAreaById: (state) => { return (areaId) => state.areaLocal.find((areaItem) => areaItem.id === areaId) }, // 新增嵌套数组的查询getter getNestedAreaById: (state) => { return (areaId) => state.areaLocal2.area.find((areaItem) => areaItem.id === areaId) }, }
2. 组件中调用
和原有getter的调用方式完全一致,建议在模板中添加可选链?.,避免传入不存在的id时,因find返回undefined导致读取name属性报错:
<script setup> import { ref } from 'vue' import { storeToRefs } from 'pinia' import { useBaseStore } from '../stores/base' const areaStore = useBaseStore() // 解构新增的getter const { getAreaById, getNestedAreaById } = storeToRefs(areaStore) const areaIndex = ref(0) const nestedAreaIndex = ref(0) </script> <template> <div class="container"> <h2>根层级AREA: {{ getAreaById(areaIndex)?.name }}</h2> <h2>嵌套AREA: {{ getNestedAreaById(nestedAreaIndex)?.name }}</h2> <!-- 其余业务代码 --> </div> </template>
可选优化:如果需要兼容非法id的场景,可以在find后添加兜底值,比如
state.areaLocal2.area.find(...) || { name: '未知区域' },从根源避免空值报错。
内容的提问来源于stack exchange,提问作者be able
相关产品推荐
相关产品推荐

