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 的回调函数,创建好的组件实例会作为回调函数的参数传入。
相关推荐
爱健身的小刘同学2 分钟前
安装 electron 依赖报错
前端·javascript·electron
耶啵奶膘3 分钟前
uniapp+vue2+uview2.0导航栏组件二次封装
前端·javascript·uni-app
布兰妮甜3 分钟前
如何使用 Tailwind CSS 构建响应式网站:详细指南
前端·css·tailwind css
MavenTalk5 分钟前
前端技术选型之uniapp
android·前端·flutter·ios·uni-app·前端开发
雨中奔跑的小孩7 分钟前
electron打包部署vue项目
javascript·vue.js·electron
ZZZCY200320 分钟前
路由策略与路由控制实验
前端·网络
shawya_void28 分钟前
javaweb-day01-html和css初识
前端·css·html
khatung29 分钟前
React——useReducer
前端·javascript·vscode·react.js·前端框架·1024程序员节
思考的橙子31 分钟前
CSS之3D转换
前端·css·3d
木子七1 小时前
vue3-setup中使用响应式
前端·vue