欢迎光临
我们一直在努力

前端通用 Pinia Token 全流程操作指南(常见常用版)

前端通用 Pinia Token 全流程操作指南(常见常用版)

本文梳理 Vue3 官方推荐状态管理库 Pinia 下的 Token 操作逻辑,剥离具体项目细节,聚焦「获取→存储→使用→过期→清除」的核心生命周期,结合 Pinia 「无 mutations、actions 直接异步、模块化更简单」的特性,每个步骤均标注「通用场景+Pinia 通用方案+注意事项」,可直接作为开发速查表。


前置说明:Pinia 与 Vuex 的核心区别(Token 操作相关)

特性VuexPinia
修改状态的方式 必须通过 commit 调用 mutations actions 中可直接修改 state
异步处理 actions 处理异步,mutations 同步 actions 可直接写 async/await
模块化 需开启 namespaced: true 隔离 天然模块化,无需额外配置
TypeScript 支持 配置复杂 原生支持,类型推导友好

一、第一步:登录成功获取并存储 Token

通用场景

用户通过账号密码/验证码等方式登录,后端验证通过后返回 Token,需将 Token 存入 Pinia(全局共享)和本地存储(刷新不丢)。

Pinia 通用方案

  • 定义 user 模块的 Pinia Store,包含 token 状态和 login 异步 action;
  • 在 login action 中调用登录接口,提取 Token;
  • 直接修改 state(无需 commit),同时存入本地存储(推荐 localStorage)。
  • 代码示例

    // 1. 定义 Pinia Store(src/stores/user.js)
    import { defineStore } from 'pinia'
    import { loginAPI } from '@/api/user' // 假设已封装好登录接口

    export const useUserStore = defineStore('user', {
    // state:必须是函数返回对象(避免组件间共享状态)
    state: () => ({
    token: localStorage.getItem('token') || '' // 初始化时从本地存储读取
    }),
    // actions:直接处理异步,可直接修改 state
    actions: {
    async login(loginForm) {
    // 调用登录接口
    const res = await loginAPI(loginForm)
    // 从接口返回中提取 Token(具体字段看后端文档)
    const token = res.data.token
    // 直接修改 state(无需 commit!Pinia 核心优势)
    this.token = token
    // 同时存入本地存储
    localStorage.setItem('token', token)
    }
    }
    })

    // 2. 组件中调用(Vue3 组合式 API 示例)
    <script setup>
    import { useUserStore } from '@/stores/user'
    const userStore = useUserStore()

    const handleLogin = async () => {
    try {
    await userStore.login({ username: 'admin', password: '123456' })
    alert('登录成功')
    // 跳转到首页(需结合路由)
    } catch (err) {
    alert('登录失败:' + (err.response?.data?.msg || '未知错误'))
    }
    }
    </script>

    注意事项

  • ❌ 不要忘记同时存 Pinia 和本地存储:Pinia 刷新页面会清空,本地存储保证刷新不丢;
  • ❌ 不要用 Vuex 的思维写 Pinia:无需 commit,直接 this.token = token 即可;
  • ❌ state 必须是函数返回对象:避免多个组件实例共享同一个 state 对象。

  • 二、第二步:请求接口时自动携带 Token

    通用场景

    每次发起业务请求时,自动从 Pinia Store 中读取 Token 并添加到请求头。

    Pinia 通用方案

  • 在 Axios/Fetch 封装的请求拦截器中读取 Pinia Store;
  • 注意:在 Vue 组件外使用 Pinia Store 时,需确保 app.use(pinia) 已执行(通常在 main.js 中先注册 Pinia)。
  • 代码示例

    // src/utils/request.js(Axios 封装)
    import axios from 'axios'
    import { createPinia } from 'pinia'
    import { useUserStore } from '@/stores/user'

    // 初始化 Pinia(组件外使用 Store 必须)
    const pinia = createPinia()
    const userStore = useUserStore(pinia)

    const service = axios.create({
    baseURL: '/api',
    timeout: 10000
    })

    // 请求拦截器:自动带 Token
    service.interceptors.request.use(
    (config) => {
    // 从 Pinia Store 中读取 Token
    const token = userStore.token
    if (token) {
    // 添加到请求头(具体字段看后端文档)
    config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
    },
    (error) => Promise.reject(error)
    )

    export default service

    注意事项

  • ❌ 不要在组件外直接 useUserStore():必须先传入 pinia 实例,否则会报错;
  • ❌ 不要在每个请求里手动加 Token:用请求拦截器统一处理;
  • ❌ 不要写错请求头字段名:必须和后端约定一致。

  • 三、第三步:处理 Token 过期

    通用场景

    Token 过期后,后端返回 401 状态码,需清除 Token 并跳转到登录页。

    Pinia 通用方案

  • 在 Axios/Fetch 封装的响应拦截器中判断 401 状态码;
  • 调用 Pinia Store 的 logout action 清除 Token;
  • 强制跳转到登录页。
  • 代码示例

    // 1. Pinia Store 补充 logout action(src/stores/user.js)
    export const useUserStore = defineStore('user', {
    state: () => ({ token: localStorage.getItem('token') || '' }),
    actions: {
    async login(loginForm) { /* 登录逻辑 */ },
    // 登出/清除 Token action
    logout() {
    // 直接修改 state
    this.token = ''
    // 清除本地存储
    localStorage.removeItem('token')
    }
    }
    })

    // 2. 响应拦截器补充(src/utils/request.js)
    import router from '@/router' // 需结合路由

    service.interceptors.response.use(
    (response) => response.data,
    (error) => {
    if (error.response && error.response.status === 401) {
    alert('登录已过期,请重新登录')
    // 调用 Pinia Store 的 logout action
    userStore.logout()
    // 跳转到登录页
    router.replace('/login')
    } else {
    alert('请求失败:' + (error.response?.data?.msg || '网络错误'))
    }
    return Promise.reject(error)
    }
    )

    注意事项

  • ❌ 不要只清除 Pinia 不清除本地存储:下次刷新页面旧 Token 又会被读出来;
  • ❌ 不要忘记跳登录页:Token 过期后用户无法继续操作;
  • ❌ 跳转登录页建议用 replace:避免用户点击“回退”回到过期页面。

  • 四、第四步:用户主动登出

    通用场景

    用户点击“退出登录”按钮,需清除所有登录相关数据。

    Pinia 通用方案

  • 给用户二次确认;
  • 调用 Pinia Store 的 logout action;
  • 跳转到登录页。
  • 代码示例

    <script setup>
    import { useUserStore } from '@/stores/user'
    import { useRouter } from 'vue-router'

    const userStore = useUserStore()
    const router = useRouter()

    const handleLogout = () => {
    if (confirm('确定要退出登录吗?')) {
    // 调用 Pinia Store 的 logout action
    userStore.logout()
    alert('退出成功')
    router.replace('/login')
    }
    }
    </script>

    注意事项

  • ❌ 不要省略二次确认:避免用户误触;
  • ❌ 登出后要彻底清除:包括 Pinia state、本地存储、用户信息(如果有);
  • ❌ 若后端有登出接口,建议先调用接口再清除前端数据。

  • 五、第五步:路由权限控制(进阶但常用)

    通用场景

    未登录用户不能访问受保护页面(如首页、个人中心),已登录用户不能访问登录页。

    Pinia 通用方案

  • 在 Vue Router 的 beforeEach 全局前置守卫中读取 Pinia Store;
  • 定义白名单,判断用户是否登录;
  • 根据判断结果决定放行或跳转。
  • 代码示例

    // src/router/index.js
    import { createRouter, createWebHistory } from 'vue-router'
    import { createPinia } from 'pinia'
    import { useUserStore } from '@/stores/user'

    const routes = [
    { path: '/login', component: () => import('@/views/Login.vue') },
    { path: '/home', component: () => import('@/views/Home.vue'), meta: { requiresAuth: true } }
    ]

    const router = createRouter({
    history: createWebHistory(),
    routes
    })

    // 初始化 Pinia(路由守卫中使用 Store 必须)
    const pinia = createPinia()

    // 全局前置路由守卫
    router.beforeEach((to, from, next) => {
    const userStore = useUserStore(pinia)
    const token = userStore.token
    const whiteList = ['/login', '/404']

    if (token) {
    to.path === '/login' ? next('/home') : next()
    } else {
    whiteList.includes(to.path) ? next() : next('/login')
    }
    })

    export default router

    注意事项

  • ❌ 不要在路由守卫中直接 useUserStore():必须先传入 pinia 实例;
  • ❌ 不要忘记定义白名单:避免无限重定向;
  • ❌ 前端权限控制仅做拦截:真正的权限校验必须在后端做。

  • 总结:Pinia Token 全流程核心逻辑

  • 获取+存储:登录接口返回 → Pinia action 直接修改 state + 存本地存储;
  • 使用:请求拦截器从 Pinia Store 读 Token → 自动加请求头;
  • 过期:响应拦截器处理 401 → 调用 Pinia logout action → 跳登录页;
  • 登出:用户确认 → 调用 Pinia logout action → 跳登录页;
  • 控制:路由守卫从 Pinia Store 读 Token → 白名单判断。

  • Pinia 专属避坑指南

  • ❌ 不要用 Vuex 的 commit/mutations 思维:Pinia 直接在 actions 中修改 this.xxx;
  • ❌ 不要在 Vue 组件外直接 useStore():必须先传入 pinia 实例;
  • ❌ state 不要写成对象:必须是函数返回对象(state: () => ({ token: '' }));
  • ❌ 不要忘记同时存 Pinia 和本地存储:Pinia 刷新会清空。
  • 赞(0)
    未经允许不得转载:171主机测评 » 前端通用 Pinia Token 全流程操作指南(常见常用版)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址