Vue Router 路由守卫详解

       在 Vue.js 应用中,Vue Router 提供了强大的路由守卫功能,用于在路由导航过程中执行特定逻辑,如权限验证、页面标题切换等。以下是路由守卫的详细介绍:

6.13 路由守卫

6.13.1 全局前置守卫

全局前置守卫是在路由切换前执行的钩子函数,可以用于权限控制等。

1. 书写位置

在创建好路由器对象之后,暴露路由器对象之前。

2. 执行时机

在初始化时执行一次,然后在每一次路由切换前都会被调用。

3. 回调函数参数

回调函数有三个参数:tofromnext

  • to:路由对象,表示要跳转到的目标路由。
  • from:路由对象,表示从哪个路由跳转而来。
  • next:函数,调用该函数表示放行,可以继续向下执行。
4. 使用示例
// 创建路由器对象
const router = new VueRouter({
    
    
  routes: [
    {
    
    
      path: '/subject1',
      component: subject1,
    },
    {
    
    
      path: '/subject2',
      component: subject2,
      meta: {
    
     isAuth: true }, // 需要鉴权的路由
    },
  ],
});

// 全局前置守卫
router.beforeEach((to, from, next) => {
    
    
  // 判断是否需要鉴权
  if (to.meta.isAuth) {
    
    
    // 验证用户权限
    if (localStorage.getItem('token')) {
    
    
      next(); // 放行
    } else {
    
    
      alert('对不起,你没有权限访问该页面');
      next('/login'); // 重定向到登录页面
    }
  } else {
    
    
    next(); // 不需要鉴权,直接放行
  }
});

6.13.2 全局解析守卫

全局解析守卫在全局前置守卫之后执行,用于在导航被确认之前、所有组件内守卫和异步路由组件被解析之后进行操作。

router.beforeResolve((to, from) => {
    
    
  if (to.meta.requiresCamera) {
    
    
    try {
    
    
      await askForCameraPermission();
    } catch (error) {
    
    
      if (error instanceof NotAllowedError) {
    
    
        // 处理错误,取消导航
        return false;
      } else {
    
    
        // 意料之外的错误,取消导航并传给全局处理器
        throw error;
      }
    }
  }
});

6.13.3 全局后置守卫

全局后置守卫是在路由切换完成后执行的钩子函数,可以用于页面标题切换等。

// 全局后置守卫
router.afterEach((to, from) => {
    
    
  // 切换页面标题
  document.title = to.meta.title || '欢迎使用';
});

6.13.4 路由独享的守卫

可以在特定路由配置中定义 beforeEnter 守卫,用于在进入该路由前执行逻辑。

const routes = [
  {
    
    
    path: '/subject2',
    component: subject2,
    beforeEnter: (to, from, next) => {
    
    
      // 验证用户权限
      if (localStorage.getItem('token')) {
    
    
        next(); // 放行
      } else {
    
    
        alert('对不起,你没有权限访问该页面');
        next('/login'); // 重定向到登录页面
      }
    },
  },
];

6.13.5 组件内的守卫

在路由组件内定义守卫,用于在进入、更新或离开路由组件时执行逻辑。

export default {
    
    
  name: 'subject2',
  beforeRouteEnter(to, from, next) {
    
    
    console.log(`进入路由组件之前: ${
      
      to.meta.title}`);
    next();
  },
  beforeRouteUpdate(to, from) {
    
    
    console.log(`路由更新: ${
      
      to.meta.title}`);
  },
  beforeRouteLeave(to, from, next) {
    
    
    console.log(`离开路由组件之前: ${
      
      from.meta.title}`);
    next();
  },
};

6.13.6 完整的导航解析流程

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

通过合理使用路由守卫,可以有效地控制路由的访问权限、优化用户体验以及实现一些特定的业务逻辑。