vue-router Navigation Guard 未成功取消路由跳转问题排查
问题根因
router.beforeEach没有正确返回异步判定结果:你把return false的拦截逻辑写在了axios请求的.then/.catch回调内部,这个返回值是给Promise回调用的,不会被导航守卫接收到。
vue-router的导航守卫如果执行异步逻辑,必须返回一个Promise,或者用async函数包裹,等异步操作结束后再由守卫本身返回放行/拦截的判定。你现在的代码发起axios请求后没有同步返回任何值,导航会默认直接放行,等请求返回打印"here"的时候,页面早就已经跳转完成了,自然拦不住。
修复代码
直接把守卫改成异步写法,让vue-router等待认证请求完成后再处理导航,同时优化了几个细节:没有本地token时直接拦截不用发请求、认证失败直接跳转登录页而不是单纯取消导航。
import { createRouter, createWebHistory } from "vue-router"; import axios from "axios"; import HomeView from "../views/HomeView.vue"; import RegisterView from "../views/RegisterView.vue"; import LoginView from "../views/LoginView.vue"; import MeHomeView from "../views/MeHomeView.vue"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: "/", name: "home", component: HomeView, }, { path: "/register", name: "register", component: RegisterView, }, { path: "/login", name: "login", component: LoginView, }, { path: "/me", name: "me", component: MeHomeView, }, ], }); router.beforeEach(async (to, from) => { // 登录、注册页直接放行 if (to.name === "login" || to.name === "register") { return true; } const accessToken = localStorage.getItem("accessToken"); // 本地无token直接跳登录,不发无效请求 if (!accessToken) { return { name: "login" }; } try { const res = await axios.post("http://localhost:4000/authenticate/", { accessToken, }); // 认证通过放行 if (res.data.code === 200) { return true; } // 认证失败跳登录 return { name: "login" }; } catch (error) { console.log(error); // 请求异常也跳回登录页 return { name: "login" }; } }); export default router;
补充说明
- 如果不想用async/await,也可以直接把axios请求的Promise实例return出去,vue-router会等待Promise resolve后拿到结果处理导航,效果完全一致
- 单纯
return false只会终止当前导航,不会给用户明确跳转反馈,实际业务里直接重定向到登录页体验更好
内容的提问来源于stack exchange,提问作者Nessi
相关产品推荐
相关产品推荐

