Nuxt3结合Pinia:如何将异步API数据正确存入状态仓库?
问题分析与解决方案
核心问题
- 模块顶层异步操作破坏Store初始化:在Pinia仓库模块顶层直接执行
await usersStore.signIn(),会干扰Store的初始化流程,刷新页面时易导致状态被重置。 - 非响应式变量无法跟踪状态变化:页面中
let invoices = []是普通变量,赋值后不会同步Store的状态更新,当Store状态因初始化问题重置时,页面数据会丢失。 - HMR配置错误:热更新监听的是
useUsersStore,而非当前的useInvoicesStore。 - 状态初始化冗余:
invoices: <any>[] || []写法冗余,类型声明不规范。
修复后的Pinia仓库代码
import { mande } from "mande"; import { acceptHMRUpdate, defineStore } from "pinia"; import { useUsersStore } from "./user"; const api = mande("http://xxx.xxx.xxx.xxx/"); export const useInvoicesStore = defineStore("invoices", { state: () => ({ invoices: [] as any[], invoice: null as any, loading: false, }), getters: { getInvoices: (state) => state.invoices, getInvoice: (state) => state.invoice, }, actions: { // 初始化授权:确保请求前用户已登录且token有效 async initAuth() { const usersStore = useUsersStore(); if (!usersStore.getAccessToken) { await usersStore.signIn("test@gmail.com", "password"); } api.options.headers.Authorization = `Bearer ${usersStore.getAccessToken}`; }, async fetchInvoices() { this.invoices = []; this.loading = true; try { await this.initAuth(); this.invoices = (await api.get("invoices")) as any[]; } catch (error) { console.error("获取发票列表失败:", error); } finally { this.loading = false; } }, async fetchInvoice(id: string) { this.invoice = null; this.loading = true; try { await this.initAuth(); this.invoice = (await api.get(`invoices/${id}`)) as any; } catch (error) { console.error("获取发票详情失败:", error); } finally { this.loading = false; } }, async createInvoice(invoice: any) { this.loading = true; try { await this.initAuth(); await api.post("invoices", invoice); await this.fetchInvoices(); // 创建成功后刷新列表 } catch (error) { console.error("创建发票失败:", error); } finally { this.loading = false; } }, async updateInvoice(id: string, invoice: any) { this.loading = true; try { await this.initAuth(); await api.patch(`invoices/${id}`, invoice); await this.fetchInvoice(id); // 更新成功后刷新详情 } catch (error) { console.error("更新发票失败:", error); } finally { this.loading = false; } }, }, }); if (import.meta.hot) { import.meta.hot.accept(acceptHMRUpdate(useInvoicesStore, import.meta.hot)); }
修复后的页面代码
<script setup> const store = useInvoicesStore(); definePageMeta({ layout: "app", }); // 使用computed保持响应式,实时跟踪Store状态变化 const invoices = computed(() => store.getInvoices); // 页面加载时触发数据获取 await store.fetchInvoices(); </script> <template> <div> <main> {{ invoices }} <div class="mx-auto max-w-7xl py-6 sm:px-6 lg:px-8"> <AppInvoiceList :invoices="invoices" /> </div> </main> </div> </template>
关键修复说明
- 异步逻辑移至Actions:将登录和授权逻辑放在
initAuth方法中,在每个请求前调用,避免模块顶层异步操作干扰Store初始化。 - 响应式绑定:用
computed绑定Store的getter,确保页面数据能实时同步Store状态,不会因刷新丢失。 - HMR修正:热更新监听当前的
useInvoicesStore,保证开发时热更新正常。 - 类型规范:用
as any[]替代冗余的类型写法,代码更清晰。
内容的提问来源于stack exchange,提问作者Maurizio Bellemo
相关产品推荐
相关产品推荐

