Skip to content

导航守卫

导航守卫

简介

在Vue中,导航守卫可以在路由切换前、切换后或者导航被触发时执行一些逻辑。

可以使用守卫来控制路由跳转、进行身份验证、进行页面权限控制等。

导航守卫钩子函数

导航守卫主要是以钩子函数实现在路由的不同时刻实现触发执行。

导航守卫主要包括以下几个钩子函数:

  1. 全局前置守卫 (beforeEach):在每个路由切换前执行。

  2. 全局解析守卫 (beforeResolve):在路由被解析时执行,在全局前置守卫后执行。

  3. 全局后置钩子 (afterEach):在每个路由切换后执行。

全局前置守卫

beforeEach 方法可以注册一个全局前置守卫,当守卫被注册后,在每次路由之前,都会执行该钩子函数。

接收参数:

  • to: 即将要进入的目标路由。
  • from: 当前导航正要离开的路由。

返回值:

  • false: 当全局前置守卫返回 false 时,会取消当前的导航,不会继续进行路由跳转。
  • 路由地址: 通过一个路由地址跳转到一个不同的地址,当前的导航被中断,然后进行一个新的导航。

全局解析守卫

beforeResolve 注册一个全局解析守卫。

beforeEach 类似,它在每次导航时都会触发,不同的是,解析守卫会在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用。

beforeResolve 是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。

接收参数:

  • to: 即将要进入的目标路由。
  • from: 当前导航正要离开的路由。

返回值:

  • false: 当全局前置守卫返回 false 时,会取消当前的导航,不会继续进行路由跳转。
  • 路由地址: 通过一个路由地址跳转到一个不同的地址,当前的导航被中断,然后进行一个新的导航。

全局后置钩子

aterEach 注册全局后置钩子,会在路由结速后执行,和守卫不同的是,全局后置钩子不会改变导航本身。

全局后置钩子对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。

全局后置勾子的参数与全局守卫相同,但没有返回值。

示例代码

  1. 首先在 views 文件夹中创建 HomeAboutNews 三个组件文件。
  2. 然后在 router 文件夹中创建 index.js 文件 做为路由管理文件。
  3. index.js 文件中添加路由配置及全局守卫钩子函数。

     // 导入路由创建函数
     import { createRouter, createWebHistory } from 'vue-router';
     // 导入 视图组件
     import Home from "../views/home.vue"
     import About from "../views/about.vue"
     import News from "../views/news.vue"
    
     // 创建路由表
     const routes = [
         {   path: "/",  component: Home },
         {   path: "/home",  component: Home, name: "Home" },
         {   path: "/about", component: About, name: "About" },
         {   path: "/news",  component: News, name: "News" }
     ]
     // 创建路由对象
     const router = createRouter({
         history: createWebHistory(),
         routes
     });
    
     // 添加路由守卫
     // 添加全局前置守卫
     router.beforeEach((to, from)=>{
         console.log("beforeEach -- from:", from, "to:", to)
         // return false
         // return {path: "/"}
         // if(to.name != "Home")
         //     return {name:"Home"}
     })
     // 添加全局解析守卫
     router.beforeResolve((to, from)=>{
         console.log("beforeResolve -- from:", from, "to:", to)
         // return false
         // if (to.name != "News")
         //     return "/news"
     })
     // 添加全局后置钩子
     router.afterEach((to, from)=>{
         console.log("afterEach -- from:", from, "to:", to)
         return "/home"
     })
     export default router;
    
  4. main.js 中将路由对象注册

     import router from "./router/index"
     app.use(router)
    
  5. 在组件中使用路由切换页面。

     <template>
         <!-- 路由入口 -->
         <router-link class="box" to="/"> Home </router-link>
         <router-link class="box" to="/home"> /Home </router-link>
         <router-link class="box" to="/about"> About </router-link>
         <router-link class="box" to="/news"> News </router-link>
         <!-- 路由出口 -->
         <router-view></router-view>
     </template>
    
     <style>
         .box{
             margin: 20px;
         }
     </style>
    

注意

vue-router 版本3和版本4在参数上有些许差别,当前教程代码使用的是版本4,关于版本3的使用方式,可自行查看官方文档了解区别。

其它导航守卫

除了全局导航守卫,VueRouter 中还提供了路由独享的守卫组件内的守卫,此部分内容在教程中做为了解内容。

路由独享的守卫

  • beforeEnter:直接在单个路由配置中添加 beforeEnter 守卫。

beforeEnter 守卫 只在进入路由时触发,不会在 paramsqueryhash 改变时触发。

例如,从 /users/2 进入到 /users/3 或者从 /users/2#info 进入到 /users/2#projects

它们只有在从一个不同的 路由导航时,才会被触发。

路由独享的守卫可以用于单个路由的身份验证和权限控制等。

const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    // 路由独享的守卫
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
]

组件内的守卫

Vue 可以在路由组件内直接定义路由导航守卫。

  • beforeRouteEnter:在跳转到该路由前的组件加载之前触发。此时组件实例尚未创建,无法访问组件实例。
  • beforeRouteUpdate:在路由即将更新(组件复用时)时触发,可以访问组件实例。
  • beforeRouteLeave:在路由离开该组件时触发,可以访问组件实例。
const UserDetails = {
  template: `...`,
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this` !
    // 因为当守卫执行时,组件实例还没被创建!
  },
  beforeRouteUpdate(to, from) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
    // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from) {
    // 在导航离开渲染该组件的对应路由时调用
    // 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
  },
}

小结

通过使用导航守卫,你可以在路由切换前、切换后或导航被触发时执行一些逻辑,从而实现对路由导航的控制和处理。这可以帮助你进行身份验证、权限控制等操作,以及实现一些动态路由切换时的效果和逻辑。