vue-router 路由守卫详解
路由守卫(Route Guard)是在路由切换时执行的一些特定函数,这些函数可以在路由导航的不同阶段被调用,以执行特定的逻辑来控制和管理路由的切换
通过编写和注册这些守卫函数,我们可以实现对路由的拦截、控制和管理,从而实现一些安全控制、权限控制、页面跳转控制等功能
导航守卫可以分为全局导航守卫
、路由独享的导航守卫
和组件级别的导航守卫
路由守卫是在导航过程中按照一定的顺序执行的异步函数。在所有守卫函数 resolve 之前,导航处于等待状态
开发者可以创建多个守卫函数,并将它们组合成一个数组。当一个导航触发时,这些守卫函数会按照顺序被依次调用
如果在守卫函数执行过程中遇到了意外情况,可能会抛出一个 Error
,这会取消导航并调用 router.onError()
注册的回调函数
每个守卫函数接收两个参数:
to
: 需要前往的路由对应的标准化路由对象 --- 需要前往的路由from
: 当前正要离开的路由对应的标准化路由对象 --- 当前正在离开的路由
守卫函数可以返回以下值:
false
: 取消当前的导航undefined
或true
: 正常执行当前导航- 一个路由字符串地址或路由对象: 跳转到返回的新路由
全局路由守卫
vue-router有三种全局路由守卫
守卫 | 函数 | 说明 | 功能 |
---|---|---|---|
全局前置守卫 | beforeEach | 在路由改变之前 | 鉴权,登录状态核对,打点等相关操作 |
全局解析守卫 | beforeResolve | 在导航被确认之前1. 所有的组件内守卫执行完毕2. 异步路由组件已经解析完成 | beforeResolve 方法可以确保路由组件及组件内回调被执行完成后再执行渲染可以避免在渲染页面之前异步组件还未加载完成的情况所以这个回调更多的是vue内部被回调 |
全局后置钩子 | afterEach | 在路由跳转完成后执行的回调注意: 此时导航已经完成,无法通过这个回调来改变导航所以它不是守卫函数,只是一个钩子函数 | 比如页面滚动到指定位置、更新页面标题等 |
// 全局前置守卫
router.beforeEach(async (to, from) => {
if (
// 检查用户是否已登录
!token &&
// ❗️ 避免无限重定向
to.name !== 'Login'
) {
// 将用户重定向到登录页面
return { name: 'Login' }
}
})
router.afterEach((to, from, failure) => {
// 第三个信息是导航失败时候的相关信息
// 如果路由导航成功 那么failure的值将会是undefined
if (!failure) sendToAnalytics(to.fullPath)
})
路由独享守卫
beforeEnter
是路由独享守卫,该守卫只有在进入路由时触发,不会在 params
、query
或 hash
改变时触发
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
return false
},
},
]
也可以将一个函数数组传递给 beforeEnter
以方便在不同路由中复用守卫函数
// 在本例中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
是唯一一个支持给 next
传递回调的守卫
next
是一个函数,在next
被回调的时候,会传入组件实例作为next
方法的参数
beforeRouteEnter (to, from, next) {
next(vm => {
// vm对应的就是组件实例
})
}
离开守卫 通常用来预防用户在离开界面时没有保存修改
beforeRouteLeave (to, from) {
const answer = window.confirm('是否确认离开')
// 通过返回false,来取消离开操作
if (!answer) return false
}
完整的导航解析流程
转载自:https://juejin.cn/post/7248073216512606266