如何在Vue多组件中导入操作Cookie的工具函数并统一校验登录状态
Vue多组件统一登录状态校验方案
一、先修正原函数的核心问题
你的原函数存在两个关键问题:
const isLoggedOut是常量,无法被重新赋值- axios请求是异步操作,直接在
then/catch里return无法拿到正确结果,函数实际返回undefined
方案1:传入组件实例给工具函数
把组件的this作为参数传给工具函数,就能直接调用$cookies:
import axios from "axios"; async function isLoggedOut(vm) { // vm即组件实例 axios.defaults.withCredentials = true; const path = `/user_authentication/protected`; try { await axios.get(path, { withCredentials: true }); return false; // 已登录 } catch (error) { console.error(error); vm.$cookies.remove("csrf_access_token"); // 通过传入的vm操作cookie return true; // 未登录 } }
组件内使用:
async checkLogin() { const loggedOut = await isLoggedOut(this); if (loggedOut) { // 处理未登录逻辑,比如跳转登录页 } }
方案2:解耦依赖,传入cookie操作函数
如果不想让工具函数依赖Vue实例,可以把移除cookie的逻辑作为参数传入:
import axios from "axios"; async function isLoggedOut(removeCsrfToken) { axios.defaults.withCredentials = true; const path = `/user_authentication/protected`; try { await axios.get(path, { withCredentials: true }); return false; } catch (error) { console.error(error); removeCsrfToken(); // 执行传入的移除cookie方法 return true; } }
组件内使用:
async checkLogin() { const loggedOut = await isLoggedOut(() => this.$cookies.remove("csrf_access_token")); if (loggedOut) { // 未登录处理 } }
二、推荐:全局统一处理(彻底避免重复代码)
上面的方式仍需每个组件手动调用,更推荐以下全局方案:
1. 路由守卫(Vue Router)
如果是页面级的登录校验,直接在路由全局守卫中统一处理:
// router/index.js import axios from "axios"; import router from "./router"; import Cookies from 'js-cookie'; // 或项目中使用的cookie工具 router.beforeEach(async (to, from, next) => { // 给需要校验的路由添加requiresAuth元信息 if (to.matched.some(record => record.meta.requiresAuth)) { axios.defaults.withCredentials = true; try { await axios.get(`/user_authentication/protected`, { withCredentials: true }); next(); // 已登录,放行 } catch (error) { console.error(error); Cookies.remove("csrf_access_token"); next({ path: "/login" }); // 跳转到登录页 } } else { next(); // 无需校验,直接放行 } });
路由配置示例:
{ path: "/dashboard", component: Dashboard, meta: { requiresAuth: true } // 标记需要登录校验 }
2. Vue全局混入
如果是组件内部的细节校验(比如按钮权限),用全局混入统一注入校验方法:
// mixins/auth.js import axios from "axios"; export default { methods: { async checkLoginStatus() { axios.defaults.withCredentials = true; try { await axios.get(`/user_authentication/protected`, { withCredentials: true }); return false; } catch (error) { console.error(error); this.$cookies.remove("csrf_access_token"); return true; } } } }
在main.js全局注册:
import authMixin from './mixins/auth'; Vue.mixin(authMixin);
组件内直接调用:
async mounted() { const loggedOut = await this.checkLoginStatus(); if (loggedOut) { // 处理未登录逻辑 } }
3. 状态管理(Pinia/Vuex)
用状态管理工具统一维护登录状态,只需初始化时校验一次,后续组件直接取状态:
以Pinia为例:
// stores/auth.js import { defineStore } from 'pinia'; import axios from "axios"; import Cookies from 'js-cookie'; export const useAuthStore = defineStore('auth', { state: () => ({ isLoggedIn: false, userInfo: null }), actions: { async checkAuth() { axios.defaults.withCredentials = true; try { const response = await axios.get(`/user_authentication/protected`, { withCredentials: true }); this.isLoggedIn = true; this.userInfo = response.data.user; return true; } catch (error) { console.error(error); Cookies.remove("csrf_access_token"); this.isLoggedIn = false; this.userInfo = null; return false; } } } });
main.js初始化校验:
import { createPinia } from 'pinia'; import { useAuthStore } from './stores/auth'; const pinia = createPinia(); app.use(pinia); const authStore = useAuthStore(); await authStore.checkAuth();
组件内直接使用状态:
import { useAuthStore } from '@/stores/auth'; export default { setup() { const authStore = useAuthStore(); // 直接通过authStore.isLoggedIn判断登录状态 return { authStore }; } }
内容的提问来源于stack exchange,提问作者adam
相关产品推荐
相关产品推荐

