阿杰,我帮你整理一份 Vue 路由守卫(Navigation Guards)详解,包括类型、使用方式、示例和注意事项。这里主要以 Vue 3 + Vue Router 4 为例。


一、概念

  • 路由守卫:在路由跳转过程中触发的钩子函数,用于控制访问权限、路由重定向、数据加载等操作
  • 核心作用
    1. 判断用户是否有权限访问页面
    2. 跳转前/跳转后执行逻辑(如请求数据、显示 Loading)
    3. 防止非法路由访问

二、路由守卫分类

类型调用时机作用范围
全局前置守卫 beforeEach路由跳转前所有路由
全局解析守卫 beforeResolve路由解析完成,组件渲染前所有路由
全局后置守卫 afterEach路由跳转完成后所有路由(不能阻止跳转)
路由独享守卫 beforeEnter路由配置中单个路由
组件内守卫 beforeRouteEnter / beforeRouteUpdate / beforeRouteLeave组件内组件级控制

三、全局守卫示例

1. 全局前置守卫 beforeEach

import router from './router';

router.beforeEach((to, from, next) => {
  // 判断是否需要登录
  if (to.meta.requiresAuth) {
    const isLogin = !!localStorage.getItem('token');
    if (!isLogin) {
      next({ name: 'Login' }); // 重定向到登录页
    } else {
      next(); // 放行
    }
  } else {
    next();
  }
});

2. 全局解析守卫 beforeResolve

router.beforeResolve((to, from, next) => {
  console.log('路由解析完成,组件渲染前');
  next();
});

3. 全局后置守卫 afterEach

router.afterEach((to, from) => {
  console.log(`从 ${from.fullPath} 到 ${to.fullPath}`);
  // 设置页面标题
  document.title = to.meta.title || 'Vue App';
});


四、路由独享守卫 beforeEnter

const routes = [
  {
    path: '/admin',
    name: 'Admin',
    component: Admin,
    beforeEnter: (to, from, next) => {
      const isAdmin = localStorage.getItem('role') === 'admin';
      if (isAdmin) next();
      else next({ name: 'Home' });
    }
  }
];


五、组件内守卫

1. beforeRouteEnter

  • 路由进入前调用,无法直接访问 this,但可以通过回调获取组件实例。
export default {
  name: 'Profile',
  beforeRouteEnter(to, from, next) {
    console.log('进入 Profile 页面前');
    next(vm => {
      // vm 是组件实例
      vm.fetchUserData();
    });
  },
  methods: {
    fetchUserData() { console.log('获取用户数据'); }
  }
}

2. beforeRouteUpdate

  • 当前路由改变,但组件复用时调用。
beforeRouteUpdate(to, from, next) {
  this.fetchUserData();
  next();
}

3. beforeRouteLeave

  • 离开当前路由前调用,可阻止离开。
beforeRouteLeave(to, from, next) {
  if (this.hasUnsavedChanges) {
    const answer = window.confirm('你有未保存的数据,确定离开吗?');
    if (answer) next();
    else next(false);
  } else {
    next();
  }
}


六、常用技巧

  1. 结合 meta 字段控制权限
{
  path: '/dashboard',
  meta: { requiresAuth: true }
}

  1. 处理异步权限或数据请求
router.beforeEach(async (to, from, next) => {
  const user = await getUserInfo();
  if (to.meta.requiresAdmin && !user.isAdmin) next('/');
  else next();
});

  1. 防止重复跳转错误(Vue Router 4)
const originalPush = router.push;
router.push = function push(location) {
  return originalPush.call(this, location).catch(err => err);
}


七、总结

  • 全局守卫:控制全局访问与权限
  • 路由独享守卫:针对单个路由的权限控制
  • 组件内守卫:处理组件级生命周期逻辑,如数据获取、确认离开

路由守卫是 前端权限控制、数据加载和页面状态管理的核心工具,在大型 SPA 项目中必不可少。