Vue-router导航守卫有哪些

191 阅读3分钟

一、导航守卫的分类(高频考点)

Vue-router的导航守卫主要分为三类,按作用范围和触发时机排序:

1. 全局守卫(应用级别)

  • 全局前置守卫router.beforeEach
    • 每次路由跳转前触发,用于登录验证、权限检查。
  • 全局解析守卫router.beforeResolve
    • 路由组件被解析后触发,用于获取数据或进度条收尾。
  • 全局后置钩子router.afterEach
    • 路由跳转完成后触发,用于页面统计、修改document.title。

2. 路由独享守卫(单个路由配置)

  • beforeEnter
    • 只在进入特定路由时触发,配置在路由对象中。

3. 组件内守卫(组件级别)

  • beforeRouteEnter
    • 进入组件前触发,此时组件实例尚未创建。
  • beforeRouteUpdate
    • 路由参数变化时触发(如从/user/1/user/2)。
  • beforeRouteLeave
    • 离开组件时触发,常用于阻止用户意外离开(如未保存表单)。

二、执行流程(关键理解)

导航守卫的完整执行顺序:

  1. 导航被触发(如点击链接、调用router.push)。
  2. 前置守卫链按顺序执行:
    • 全局beforeEach → 路由独享beforeEnter → 组件内beforeRouteEnter
  3. 路由组件被解析(异步组件加载完成)。
  4. 全局解析守卫beforeResolve执行
  5. 导航确认(此时路由已跳转)。
  6. 全局后置钩子afterEach执行
  7. 触发DOM更新
  8. 组件内beforeRouteUpdate(若路由参数变化)

三、典型应用场景(结合项目经验)

1. 登录验证

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isAuthenticated()) {
    next('/login'); // 未登录时重定向到登录页
  } else {
    next(); // 继续导航
  }
});

2. 权限控制

router.beforeEach((to, from, next) => {
  if (to.meta.role === 'admin' && !currentUser.isAdmin) {
    next('/forbidden'); // 无权限时重定向
  } else {
    next();
  }
});

3. 路由切换动画

// 全局前置守卫设置过渡效果
router.beforeEach((to, from, next) => {
  document.body.classList.add('page-loading');
  next();
});

// 全局后置钩子移除过渡效果
router.afterEach(() => {
  setTimeout(() => {
    document.body.classList.remove('page-loading');
  }, 300);
});

4. 阻止未保存表单离开

export default {
  beforeRouteLeave(to, from, next) {
    if (this.formDirty) { // 表单已修改但未提交
      if (confirm('确认离开?未保存的内容将丢失。')) {
        next(); // 允许离开
      } else {
        next(false); // 取消导航
      }
    } else {
      next();
    }
  }
};

四、实现细节与注意事项(高频陷阱)

1. next()的正确用法

  • 必须调用:每个守卫都必须调用next()来 resolve 钩子,否则导航会被挂起。
  • 禁止多次调用next()只能调用一次,多次调用会导致警告。
  • 参数含义
    • next():继续正常导航;
    • next(false):取消当前导航;
    • next('/path')next({ path: '/path' }):重定向到指定路径。

2. 组件内守卫的特殊性

  • beforeRouteEnter中无法访问this(组件实例尚未创建),需通过next(vm => {})访问:
    beforeRouteEnter(to, from, next) {
      next(vm => {
        // 通过vm访问组件实例
        console.log(vm.$data);
      });
    }
    

3. 异步操作处理

  • 若守卫中存在异步操作(如API请求),需等待异步完成后再调用next()
    router.beforeEach(async (to, from, next) => {
      const user = await fetchUser();
      if (user.isAdmin) {
        next();
      } else {
        next('/login');
      }
    });
    

五、总结

“Vue-router的导航守卫是控制路由访问和生命周期的核心机制,主要分为:

  1. 全局守卫:应用级别拦截(如登录验证);
  2. 路由独享守卫:单个路由配置(如特定页面权限);
  3. 组件内守卫:组件级别控制(如阻止未保存表单离开)。

其执行流程是一个链式调用,从全局到路由再到组件,最终通过next()方法决定导航结果。在实际项目中,我会用全局前置守卫处理登录态,用组件内守卫优化用户体验,并注意避免next()的误用导致导航异常。”