Vue3+Pinia页面mounted时读取localStorage令牌为null如何解决
问题原因
- 你的axios实例初始化时机不对:
http-common.js第一次被项目内模块导入时就会执行创建实例的逻辑,这个时机远早于用户登录存入token的时间,创建实例时写在headers里的localStorage.getItem('accessToken')直接读到了null,且这个默认头是实例初始化时就固定的,后续你往localStorage写了新的token,已经创建好的axios实例不会自动更新这个头的值,所以请求一直带Bearer null。 - Pinia用法不符合规范:getters是用来做同步状态派生计算的,和Vue的computed属性逻辑一致,不支持异步请求逻辑,你把接口调用写在getters里本身就无法正常工作,异步逻辑应该定义在actions中。
修复方案
1. 改造axios封装,通过请求拦截器动态注入token
不要在创建axios实例时写死Authorization请求头,改成每次发送请求前通过拦截器实时读取localStorage中最新的token,彻底解决初始化时机问题,修改http-common.js代码如下:
import axios from "axios"; const http = axios.create({ baseURL: "https://api-domain/api/", }); // 请求拦截器:发起请求前动态追加最新鉴权头 http.interceptors.request.use((config) => { const accessToken = localStorage.getItem("accessToken"); if (accessToken) { config.headers.Authorization = `Bearer ${accessToken}`; } return config; }, (error) => Promise.reject(error)); export default http;
2. 修正Pinia Store结构,把异步请求移到actions
移除getters里的异步逻辑,新增对应的action方法处理数据拉取,注意不要让action名和state字段重名避免冲突,修改profile store代码如下:
import { defineStore } from "pinia"; import http from '../http-common'; export const useProfile = defineStore("profile", { state: () => ({ userSummary: {}, error: null }), actions: { async fetchUserSummary() { try { const res = await http.get('dashboard'); this.userSummary = res.data.data; } catch (error) { this.error = error; } } } });
3. 调整仪表盘页面的调用逻辑
onMounted生命周期中调用刚定义的action方法拉取数据,而非访问属性,修改视图代码如下:
<script setup> import {onMounted} from "vue"; import {useProfile} from "../stores/profile"; const profile = useProfile(); onMounted(() => { profile.fetchUserSummary(); }); </script>
可选优化:可以给axios实例追加响应拦截器,统一处理401鉴权失败逻辑,比如token过期时清空本地存储的凭证、跳转回登录页,不需要在每个接口请求里单独写判断。
内容的提问来源于stack exchange,提问作者Mena
相关产品推荐
相关产品推荐

