Vue3.2 <script setup>中API服务调用Pinia store报错求助
解决Vue 3.2中API服务访问Pinia Store的初始化错误
问题描述
使用Vue 3.2的<script setup>语法时,在API服务中访问Pinia Store出现以下错误:
Uncaught ReferenceError: Cannot access 'store' before initialization at api.js?:9:1
原始代码
src/services/api.js(首次尝试):
import axios from 'axios'; import store from '../stores/index'; const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_URL }); if (store) { const { token } = store; if (token) { api.defaults.headers.Authorization = `Bearer ${token}`; } } console.log(api); export default api;
src/stores/index.ts:
import { defineStore } from 'pinia' import Project from '../models/Project'; import { grantAuthSshd, revokeAuth, parseJwt } from '../services/auth'; const initialUser = JSON.parse(sessionStorage.getItem('Orcamento:token') || '{}'); const useProject = defineStore('project-store', { state: () => ({ loading: false as boolean, }), actions: { loadingDataTable(status: ((status: boolean) => void) & boolean) { this.loadingDataTable = status; }, } });
拦截器尝试仍报错
import axios from 'axios'; import useProject from '../stores/index'; const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_URL }); api.interceptors.request.use( (config) => { const { token } = store; if ({token}) { api.config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); } ); const store = useProject(); export default api;
错误原因分析
- Store导出错误:
src/stores/index.ts中导出的是defineStore返回的创建Store的函数,而非实例化后的Store对象,直接import并当作实例使用会出错。 - 提前引用变量:拦截器尝试中,回调函数里引用了尚未声明的
store变量,导致初始化顺序错误。 - Store缺少token字段:原始Store的state中没有定义
token,无法获取令牌值。 - 拦截器修改对象错误:尝试修改
api.config.headers而非请求传入的config.headers,无法正确设置请求头。
解决方案
1. 修正Store定义与导出
完善Store的state字段,并导出创建Store的函数:
// src/stores/index.ts import { defineStore } from 'pinia' import Project from '../models/Project'; import { grantAuthSshd, revokeAuth, parseJwt } from '../services/auth'; const initialUser = JSON.parse(sessionStorage.getItem('Orcamento:token') || '{}'); // 导出创建Store的函数,命名更清晰 export const useProjectStore = defineStore('project-store', { state: () => ({ loading: false as boolean, // 添加token字段,从sessionStorage初始化 token: initialUser.token || '' }), actions: { // 修正actions中的赋值错误,对应state里的loading字段 loadingDataTable(status: boolean) { this.loading = status; }, } });
2. 修正API服务中的Store调用
在请求拦截器内部动态获取Store,确保Pinia实例已激活:
// src/services/api.js import axios from 'axios'; import { useProjectStore } from '../stores/index'; import { getActivePinia } from 'pinia'; const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_URL }); api.interceptors.request.use( (config) => { // 确保Pinia实例已创建,再获取Store const activePinia = getActivePinia(); if (activePinia) { const store = useProjectStore(activePinia); if (store.token) { // 修改当前请求的config.headers,而非全局api.config config.headers.Authorization = `Bearer ${store.token}`; } } return config; }, (error) => { return Promise.reject(error); } ); export default api;
关键说明
- 避免模块顶级调用Store:Pinia需要在Vue应用实例初始化并安装Pinia插件后才能正常使用Store,因此不能在模块顶级直接调用
useProjectStore(),需在运行时回调(如拦截器、组件钩子)中调用。 - 使用
getActivePinia():确保获取到已激活的Pinia实例,防止因实例未初始化导致的错误。 - 正确修改请求头:拦截器中需修改传入的
config对象的headers,该对象对应当前请求的配置,修改后返回才能生效。
内容的提问来源于stack exchange,提问作者Hugo Pedro
相关产品推荐
相关产品推荐

