Vue-Router入门(七) :路由守卫详解

路由守卫是什么?

官方解释:

"导航"表示路由正在发生改变。vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

导航守卫就是路由跳转过程中的一些钩子函数。 路由跳转是一个大的过程,这个大的过程分为跳转前中后等等细小的过程,在每一个过程中都有一函数,这个函数能让你操作一些其他的事,这就是导航守卫。类似于Vue的生命周期钩子函数。

路由守卫的分类

路由守卫有多种类别,大致可以分为全局的,单个路由独享的,或者组件级的。以下是这几种类别的区别。

  • 全局守卫:是指路由实例上直接操作的钩子函数,特点是所有路由配置的组件都会触发,直白点就是触发路由就会触发这些钩子函数

  • 路由守卫:是指在单个路由配置的时候也可以设置的钩子函数

  • 组件守卫: 是指在组件内执行的钩子函数,类似于组件内的生命周期,相当于为配置路由的组件添加的生命周期钩子函数。

路由守卫中回调函数的参数

每个守卫方法接收三个参数:

  • to: 即将要进入的目标
  • from: 当前导航正要离开的路由
  • next :涉及到next参数的钩子函数,必须调用next()方法来resolve这个钩子,否则路由会中断在这,不会继续往下执行。注意,这个参数是可选的。

路由守卫详解

全局路由守卫

守卫 函数 说明 功能
全局前置守卫 beforeEach 在路由改变之前 鉴权,登录状态核对,打点等相关操作
全局解析守卫 beforeResolve 在导航被确认之前 1. 所有的组件内守卫执行完毕 2. 异步路由组件已经解析完成 beforeResolve方法可以确保路由组件及组件内回调被执行完成后再执行渲染 可以避免在渲染页面之前异步组件还未加载完成的情况 所以这个回调更多的是vue内部被回调
全局后置钩子 afterEach 在路由跳转完成后执行的回调 注意: 此时导航已经完成,无法通过这个回调来改变导航 所以它不是守卫函数,只是一个钩子函数 比如页面滚动到指定位置、更新页面标题等

全局前置守卫

js 复制代码
// 全局前置守卫
router.beforeEach((to, from, next) => { 
    if (to.name !== 'Login' && !isAuthenticated) {
        next({ name: 'Login' })
    }
    else next()
}
)

全局解析守卫

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

全局后置钩子

和守卫不同的是,全局后置钩子不会接受 next 函数也不会改变导航本身:

js 复制代码
router.afterEach((to, from) => {
  sendToAnalytics(to.fullPath)
})

路由独享守卫

beforeEnter是路由独享守卫,该守卫只有在进入路由时触发,不会在 paramsqueryhash 改变时触发

js 复制代码
const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
]

也可以将一个函数数组传递给 beforeEnter 以方便在不同路由中复用守卫函数

js 复制代码
// 在本例中removeQueryParams被复用了两次
const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: [removeQueryParams, removeHash],
  },
  {
    path: '/about',
    component: UserDetails,
    beforeEnter: [removeQueryParams],
  },
]

组件内守卫

组件内守卫指的是在路由组件内直接定义的导航守卫函数。 也就是说组件内守卫只能在路由组件中使用,在渲染到<router-view />的子组件中是不存在组件内守卫的。

守卫 说明
beforeRouteEnter 异步组件加载完毕,组件实例化之前 不可以访问组件实例 this
beforeRouteUpdate 当前路由改变,但是该组件被复用时调用 如/users/1/users/2之间之间进行跳转的时候 可以访问组件实例 this
beforeRouteLeave 离开该组件的时候 可以访问组件实例 this

beforeRouteEnter

beforeRouteEnter是唯一一个支持给 next 传递回调的守卫

js 复制代码
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this` !
    // 因为当守卫执行时,组件实例还没被创建!
  },

beforeRouteUpdate

在当前路由改变时,并且该组件被复用时调用,可以通过this访问实例。

js 复制代码
  beforeRouteUpdate(to, from) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
    // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
  },

beforeRouteLeave

离开守卫 通常用来预防用户在离开界面时没有保存修改

js 复制代码
beforeRouteLeave (to, from) {
  const answer = window.confirm('是否确认离开')
  // 通过返回false,来取消离开操作
  if (!answer) return false
}

完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
相关推荐
计算机学姐7 分钟前
基于微信小程序的调查问卷管理系统
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
学习使我快乐013 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
bobostudio19953 小时前
TypeScript 设计模式之【策略模式】
前端·javascript·设计模式·typescript·策略模式
黄尚圈圈4 小时前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水5 小时前
简洁之道 - React Hook Form
前端
正小安7 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch9 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光9 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   9 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发