Vue Router 导航守卫
导航守卫
导航守卫
‘导航’表示路由正在发生改变。
vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
路由跳转并不是任何时候都允许跳转,例如登录页面,只有用户名和密码输入正确才能跳转,而这时候就需要导航守卫来控制(阻拦和放行)。
有很多方式植入路由导航中:全局的、单个路由独享的、组件级的。
参数(params)或查询(query)的改变并不会触发进入/离开的导航守卫,如果想在其改变时做些什么,可以通过watch $route对象来应对这些变化,或使用beforeRouteUpdate的组件内守卫。
全局前置守卫
使用router.beforeEach注册一个全局前置守卫。
只要项目跳转,该方法一定会在跳转前触发。
对于全局守卫来说,单独创建一个js文件存放会更好。
each.js:
import router from "@/router/index";
router.beforeEach((to, from, next) => {
//....
})
main.js:
import './router/each'
每个守卫方法接收三个参数:to、from、next
举个栗子🌰:
现有路径'/'即将跳转到'/about'
to:Route 即将要进入的目标路由对象
from:Route 当前导航正要离开的路由(对象)
next:function 一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。
确保next函数在任何给定导航守卫中都被严格调用一次,可出现多于一次,但只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析(条件不满足,没有机会执行)或报错(逻辑路径冲突)。
带不同参数的next() | 含义 |
next() |
进行管道中的下一个钩子。 若去全部钩子都执行完了,则导航的状态就是confirmed(确认的)。 |
next(false) |
中断当前导航。 若浏览器的URL改变了(用户手动或浏览器后退按钮),则URL地址会重置到from路由对应的地址。 |
next('/xxxx')或next({path:'/xxxx'}) |
跳转到一个不同的地址。当前导航被中断,然后进行一个新的导航。 可以向next传递任意位置对象,且允许设置如replace:true、name:'Home'之类的选项以及任何用在<router-link>的to属性或router.push()参数中的选项。 |
next(error) | 若传入next的参数是一个Error实例,则导航会被终止且该错误会被传递给router.onError()注册过的回调。 |
全局解析守卫
使用router.beforeResolve注册一个全局(解析)守卫。
与router.beforeEach类似,区别是在导航被确认之前(跳转前),同时在所有组件内守卫和异步路由组件被解析之后(解析后),解析守卫就被调用。
router.beforeResolve((to, from, next) => {
//......
})
全局后置钩子
与守卫不同,这些后置钩子不会接受next函数也不会改变导航本身。
守卫:导航前
钩子:导航后(已跳转,不需要next()了)
使用router.afterEach注册全局后置钩子。
router.afterEach((to, from) => {
//......
})
路由独享的守卫
可以在路由配置上直接定义beforEnter守卫。
const routes = [
{
path: '/',
component: () => import('@/views/Home'),
beforeEnter: (to, from, next) => {
//.......
}
}
]
组件内的守卫
在路由组件内直接定义以下路由导航守卫:
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
export default {
name: "Home",
beforeRouteEnter(to, from, next) {
//......
},
beforeRouteUpdate(to, from, next) {
//......
},
beforeRouteLeave(to, from, next) {
//......
}
}
beforeRouteEnter | beforeRouteUpdate | beforeRouteLeave | |
触发 |
在渲染该组件的对应路由被confirm前调用 组件被复用时是不会调用beforeRouterEnter的 |
在当前路由改变,但该组件被复用时调用 1.路由路径带有动态段,只有动态段变化
2.路由路径从访问组件到访问子组件 子组件路由路径是绝对路径还是相对路径都可以
|
导航离开该组件的对应路由时调用 |
是否可以获取this |
不能获取组件实例‘this’ 因为当该组件守卫执行前,组件实例还没被创建 |
可以访问实例'this' |
可以访问实例'this' |
针对this |
通过传一个回调函数给next(),来访问组件实例 在导航被confirm的时候执行回调,且把组件实例作为回调方法的参数
|
||
是否支持给next传递回调 | 是(唯一支持的守卫) | 否 (能直接访问this,没必要) | 否(能直接访问this,没必要) |
应用 |
通常用来禁止用户在还未保存修改前突然离开,阻止导航,且询问用户是否未保存就离开 next() 放行 next(false) 取消导航,留在当前页面
|
完整的导航解析流程
1.导航被触发(接收到from路由,且上一轮的导航已经结束,但仍停留在上一个组件里)(触导)
2.在失活的组件里调用beforeRouteLeave守卫(离失活组)
3.调用全局beforeEach守卫(全进)
4.如果存在复用的组件,在复用组件里调用beforeRouteUpdate守卫(复组更)
5.在路由配置里调用beforeEnter(路进)
6.解析异步路由组件(解析异步路)
7.在被激活的组件里调用beforeRouteEnter(进激活组)
8.调用全局beforeResolve守卫(全析)
9.导航被确认(confirm)
10.调用全局afterEach钩子(全完)
11.触发DOM更新 但这时候还没有执行生命周期钩子,还没有创建vue实例并挂载,所以只是页面数据当前并没有发生改变
12.调用beforeRouteEnter守卫中传给next的回调函数,创建好的实例会作为参数传入(组件实例建好传回调)
守卫/钩子总结🥗:
全局3个(2守卫 1钩子):beforeEach、beforeResolve、afterEach
路由守卫1个:beforeEnter
组件守卫3个:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave