Vue项目中Axios拦截器调用Vue Router跳转登录页报错问题
Vue项目Axios拦截401跳转登录时Router未定义问题解决
问题场景
需求是后端返回401-Unauthorised错误时自动跳转到登录页,但在Axios响应拦截器中调用router.push('/login')时,控制台提示router is undefined。现有代码如下:
axios.js代码
import Vue from 'vue' import axios from "axios" import router from '../router' const _axios = axios.create({ // 你的Axios配置项 }) _axios.interceptors.response.use( function(response) { return response }, function(error) { if(error.response.status == 401){ router.push('/login') } return Promise.reject(error) } ) export default _axios
router.js代码
import Vue from 'vue' import VueRouter from 'vue-router' import store from '../store' Vue.use(VueRouter) const routes = [ { path: '/login', name: 'Login', meta: { layout: 'login', requireAuth: false, icon: null }, component: () => import(/* webpackChunkName: "login" */ '../components/common/auth/login-form'), } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
两种导入方式的报错原因
情况1:解构导入{router}时报错
代码写成import { router } from '../router'时,终端执行npm run serve报错,原因是router.js使用的是默认导出(export default router),而非命名导出。解构导入仅适用于命名导出(如export const router = ...),所以找不到对应的导出项。
情况2:默认导入router时报错
使用import router from '../router'时仍报错,核心原因是循环依赖或模块初始化顺序问题:
- 若router.js中导入的store模块又导入了axios,会形成
axios → router → store → axios的循环依赖,导致axios初始化时router还未完成创建; - 若main.js中先导入axios再导入router,axios初始化时router实例还未生成,拿到的router为undefined。
解决方案
方案1:通过Vue原型挂载Router(推荐)
在main.js中先初始化router,再将其挂载到Vue原型上,axios中直接通过原型调用,避免直接导入router:
- 修改main.js:
import Vue from 'vue' import App from './App.vue' import router from './router' import axios from './axios' // 将router挂载到Vue原型 Vue.prototype.$router = router Vue.prototype.$axios = axios new Vue({ router, render: h => h(App) }).$mount('#app')
- 修改axios.js:
import Vue from 'vue' import axios from "axios" const _axios = axios.create({ // 你的Axios配置 }) _axios.interceptors.response.use( function(response) { return response }, function(error) { // 加可选链避免error.response为undefined时报错 if(error.response?.status === 401){ Vue.prototype.$router.push('/login') } return Promise.reject(error) } ) export default _axios
方案2:动态导入Router(避免初始化顺序问题)
在拦截器触发401时才动态导入router,跳过初始化阶段的依赖问题:
修改axios.js:
import Vue from 'vue' import axios from "axios" const _axios = axios.create({ // 你的Axios配置 }) _axios.interceptors.response.use( function(response) { return response }, async function(error) { if(error.response?.status === 401){ // 动态导入router模块,取default导出项 const routerModule = await import('../router') routerModule.default.push('/login') } return Promise.reject(error) } ) export default _axios
额外优化建议
- 拦截401时建议同时清除用户token(若有),避免重复触发401;
- 增加
error.response的判断,防止网络错误等场景下error.response为undefined导致报错。
内容的提问来源于stack exchange,提问作者Darshan Soni
相关产品推荐
相关产品推荐

