【vue高频面试题—路由篇】:vue-router 路由导航守卫有哪些 在哪些场景适用

80 阅读3分钟

Vue Router 提供了多种 路由导航守卫,用于控制导航行为、权限校验、数据预加载等操作。导航守卫按触发时机和作用范围分类,主要有以下几类:


1. 全局守卫

这些守卫会在每次路由发生变化时触发,适合全局性的操作,比如登录状态检查、统计埋点。

1.1 beforeEach

  • 触发时机:在每次路由跳转前触发。

  • 使用场景

    • 校验用户是否有权限进入目标路由。
    • 跳转到登录页面(如未登录)。
    • 设置页面标题。
  • 示例

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

1.2 beforeResolve

  • 触发时机:在组件内守卫(如 beforeRouteEnter)之后,也在 beforeEach 后触发。

  • 使用场景

    • 确保所有异步数据加载完成后再进入路由。
    • 适用于精细化控制导航。
  • 示例

    router.beforeResolve((to, from, next) => {
      // 执行某些异步任务
      loadData().then(() => {
        next(); // 数据加载完成后继续
      });
    });
    

1.3 afterEach

  • 触发时机:路由跳转完成后触发。

  • 使用场景

    • 记录页面访问统计(如 Google Analytics)。
    • 复位页面状态或滚动位置。
  • 示例

    router.afterEach((to, from) => {
      console.log(`Navigated from ${from.path} to ${to.path}`);
    });
    

2. 路由独享守卫

为某个特定路由定义守卫,直接在路由配置中设置。

beforeEnter

  • 触发时机:在进入该路由之前触发。

  • 使用场景

    • 针对单个路由进行权限校验。
    • 加载路由特定的资源。
  • 示例

    const routes = [
      {
        path: '/dashboard',
        component: Dashboard,
        beforeEnter: (to, from, next) => {
          if (hasPermission()) {
            next();
          } else {
            next('/login'); // 重定向
          }
        }
      }
    ];
    

3. 组件内守卫

在组件内直接定义,适用于需要组件参与的路由控制。

3.1 beforeRouteEnter

  • 触发时机:在路由进入之前调用。

  • 特点:可以通过回调函数访问组件实例(此时组件还未创建)。

  • 使用场景

    • 获取组件实例时需要访问路由相关数据。
    • 页面级别的权限检查。
  • 示例

    export default {
      beforeRouteEnter(to, from, next) {
        next(vm => {
          vm.loadData(); // 访问组件实例
        });
      }
    };
    

3.2 beforeRouteUpdate

  • 触发时机:在当前路由改变(但仍渲染同一组件)时调用。

  • 使用场景

    • 处理动态路由参数变化(如 /user/:id)。
  • 示例

    export default {
      beforeRouteUpdate(to, from, next) {
        this.userId = to.params.id; // 更新组件内数据
        next();
      }
    };
    

3.3 beforeRouteLeave

  • 触发时机:在导航离开当前路由时触发。

  • 使用场景

    • 提示用户未保存的更改。
    • 防止意外导航(如关闭表单页面时提示)。
  • 示例

    export default {
      beforeRouteLeave(to, from, next) {
        if (this.hasUnsavedChanges) {
          const confirm = window.confirm('您有未保存的更改,确定要离开吗?');
          if (confirm) next();
          else next(false);
        } else {
          next();
        }
      }
    };
    

总结

类型守卫使用场景
全局守卫beforeEach全局权限校验、跳转控制
beforeResolve在组件守卫之前精细化控制导航
afterEach记录日志、埋点或重置状态
路由独享守卫beforeEnter特定路由的权限校验或数据加载
组件内守卫beforeRouteEnter异步加载数据,访问组件实例
beforeRouteUpdate动态参数更新时处理逻辑
beforeRouteLeave离开前提醒(如未保存表单)

完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫(2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。