You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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>

问题原因及解决方法

核心问题

  1. Store实例获取错误:createTableStore返回的是Store定义(StoreDefinition),不是直接的Store实例。你直接将其断言为CustomStore属于类型欺骗,实际对象并非Store实例,自然无法访问table等属性。
  2. 模板变量名错误:模板中使用的typedToUploadStore未定义,正确变量名应为typedToUploadTableStore。

修正方案

  1. 获取正确的Store实例:调用createTableStore返回的Store定义函数,才能得到可直接使用的Store实例(Pinia会自动注入上下文)。
  2. 移除无效类型断言:调用Store定义函数后,TypeScript会自动推断出正确的CustomStore类型,无需手动断言。
  3. 修正模板变量名:将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:37:03