在Vue模板中使用Pinia Store的table变量时为何出现undefined?
问题
我创建了一个包含table变量的Pinia Store工厂函数,但在Vue组件中声明Store并尝试使用其中的table变量时,却得到了undefined。我曾尝试在工厂函数内使用onBeforeMount生命周期钩子,但并未解决问题。
Pinia Store工厂函数代码
import { StoreDefinition, defineStore } from 'pinia'; import { ref } from 'vue'; import { useStorage } from '@vueuse/core'; import type { Ref } from 'vue'; import type { RemovableRef } from '@vueuse/core'; import type { Table } from "@/types/generalTypes"; import { customDateFormatter } from '@/composables/useDateFormatter'; export type CustomStore = { table: RemovableRef<Table>; addToTable: (rowToAdd: Record<string, any>) => Table; removeFromTable: (indexToRemove: number) => Table; returnItemFromTable: (indexToReturn: number) => Record<string, string>; loading: Ref<boolean>; }; export const createTableStore = (id: string): StoreDefinition<string, any> => { const storageKey = `table_${id}`; return defineStore(id, () => { const table: RemovableRef<Table> = useStorage(storageKey, { headers: [], data: [] }); const loading = ref(false); function addToTable(rowToAdd: Record<string, any>): Table { loading.value = true; const tempTable: Record<string, any> = {}; for (const key in rowToAdd) { if (rowToAdd[key] == null) return table.value; if (rowToAdd[key] instanceof Date) { tempTable[key] = customDateFormatter(rowToAdd[key]); continue; } tempTable[key] = rowToAdd[key]; } table.value.data.push(tempTable); setTimeout(() => loading.value = false, 1000); return table.value; } function removeFromTable(indexToRemove: number): Table { loading.value = true; table.value.data = table.value.data.filter((_, index) => index !== indexToRemove); setTimeout(() => loading.value = false, 1000); return table.value; } function returnItemFromTable(indexToReturn: number): Record<string, string> { const item = table.value.data.find((_, index) => index === indexToReturn); return item; } return { table, addToTable, removeFromTable, returnItemFromTable, loading } as CustomStore; }); }
Vue组件代码
<script setup lang="ts"> import { ref, inject } from 'vue'; import type { Ref } from 'vue'; import BaseForm from '@/components/BaseForm.vue'; import Table from '../Tables/Table.vue'; import FormFilePicker from '../FormComponents/FormFilePicker.vue'; import { createTableStore } from '@/stores/tableStore'; import type { CustomStore } from '@/stores/tableStore'; const projectData = inject('projectData'); const toUploadTableStore: unknown = createTableStore('to-upload-table'); const typedToUploadTableStore = toUploadTableStore as CustomStore; const fromDatabaseStore: unknown = createTableStore('from-database-table'); const typedFromDatabaseStore = fromDatabaseStore as CustomStore; function passToTable(files: { src: File }[]): void { const date = new Date(); for (const file of files) { const fileName = file.src.name; const fileType = file.src.type; typedToUploadTableStore.addToTable({ fileType, date, fileName }); } } </script> <template> <div> <Table :headers="[ { id: 0, description: 'Πολυμέσα' }, { id: 1, description: 'Ημ. Δημιουργίας' }, { id: 2, description: 'Αρχείο' } ]" :data="typedToUploadStore.table.value.data" :tableModifiers="{ canDeleteItem: true }" @delete-item="(index: number) => typedToUploadTableStore.removeFromTable(index)" /> </div> </template>
问题原因及解决方法
核心问题
- Store实例获取错误:
createTableStore返回的是Store定义(StoreDefinition),不是直接的Store实例。你直接将其断言为CustomStore属于类型欺骗,实际对象并非Store实例,自然无法访问table等属性。 - 模板变量名错误:模板中使用的
typedToUploadStore未定义,正确变量名应为typedToUploadTableStore。
修正方案
- 获取正确的Store实例:调用
createTableStore返回的Store定义函数,才能得到可直接使用的Store实例(Pinia会自动注入上下文)。 - 移除无效类型断言:调用Store定义函数后,TypeScript会自动推断出正确的
CustomStore类型,无需手动断言。 - 修正模板变量名:将
typedToUploadStore改为typedToUploadTableStore,同时模板中访问Ref类型无需加.value(Vue会自动解包)。
修改后的组件代码
<script setup lang="ts"> import { ref, inject } from 'vue'; import type { Ref } from 'vue'; import BaseForm from '@/components/BaseForm.vue'; import Table from '../Tables/Table.vue'; import FormFilePicker from '../FormComponents/FormFilePicker.vue'; import { createTableStore } from '@/stores/tableStore'; const projectData = inject('projectData'); // 调用Store定义函数获取实例,类型自动推断 const typedToUploadTableStore = createTableStore('to-upload-table')(); const typedFromDatabaseStore = createTableStore('from-database-table')(); function passToTable(files: { src: File }[]): void { const date = new Date(); for (const file of files) { const fileName = file.src.name; const fileType = file.src.type; typedToUploadTableStore.addToTable({ fileType, date, fileName }); } } </script> <template> <div> <Table :headers="[ { id: 0, description: 'Πολυμέσα' }, { id: 1, description: 'Ημ. Δημιουργίας' }, { id: 2, description: 'Αρχείο' } ]" <!-- 模板自动解包Ref,无需加.value --> :data="typedToUploadTableStore.table.data" :tableModifiers="{ canDeleteItem: true }" <!-- 直接传递函数引用,简化写法 --> @delete-item="typedToUploadTableStore.removeFromTable" /> </div> </template>
内容的提问来源于stack exchange,提问作者Wingrider33
相关产品推荐
相关产品推荐

