守卫:即路由触发时,在被确认之前所要执行的函数,可以启到本次跳转的拦截作用,可以决定本次跳转成功与否。
钩子:即路由触发时机要执行的函数,不能起到拦截组用,不能干预本次跳转的成功与否。
一、分类
1.从调用时机来分,为两类:守卫、钩子
守卫:beforeEach、beforeRouteUpdate、beforeEnter、beforeRouteEnter、beforeReslove、beforeRouteLeave
钩子:afterEach
2.从其挂载点来分,分为三类:全局的、路由自己的、组件内部的
全局的:befroeEach、beforeReslove、afterEach
路由自己的:beforeEnter
组件内部的:beforeRouteUpdate、beforeRouteEnter、beforeRouteLeave
二、各个调用时机
1.beforeEach:跳转触发后,导航confirmed之前,在此过程中,所有钩子处于等待状态。
2.beforeReslove:在导航confirmed之前,在所有组件内部守卫和路由守卫执行完毕之后调用。
3.afterEach:在导航confirmed之后调用。
4.beforeEnter:解析异步路由组件之前调用,值得注意的是,如果两次路由的切换访问的是同一个组件,只是传递了不同的参数,那么beforeRouteUpdate要早于beforeEnter执行。
如果两次路由为同一组件,如查询商品详情,只是更换商品id,那将不会触发mounted生命钩子,这种应用场景下应把初始化数据的处理代码放到beforeRouteUpdate钩子中执行
5..beforeRouteUpdate:当路由组件复用时,调用。在beforeEnter之前。
6.beforeRouteEnter:路由组件解析完成以后,组件实例创建之前执行,此时并未创建组件实例,所以内部不能调用this,但其next函数可以接受一个回调函数,此函数接受一个实例参数,在导航confirmed后执行回调函数。
beforeRouterEnter(to,from,next){
next(vm=>{
console.log("此时才能访问vue实例,即vm")
})
}
7.beforeRouteLeave:离开组件时调用,可用来做一些提示操作。
值得注意的是,除了afterEach之外,每个钩子都接受了一个next参数,此参数为一个函数,在钩子内部需要我们手动调用,不调用则跳转中断,另外此函数可以接受一个地址字符串,表示跳转到其他地址。
三、举例说明调用时机
假设当前在A组件触发超链接跳往B组件。路由守卫&钩子的执行过程如下:
1.超链接被触发;
2.在A组件执行beforeRouteLeave函数---(组件内部的)
3.调用beforeEach函数---(全局的)
4.如果B是复用的组件,嗲用beforeRouteUpdate函数---(组件内部的)
5.解析路由组件B前,调用beforeEnter函数---(路由的)
6.解析路由异步组件B
7.导航confirmed前调用beforeReslove函数---(全局的)
8.导航确认
9.B组件创建前调用beforeRouteEnter函数---(组件内部的)
10.调用afterEach函数---(全局的)
11.创建B组件实例,DOM更新
12.执行beforeRouteEnter的回调函数,传入当前的B实例为参数。
到此完成一次导航。
组件内部--全局--组件内部--路由--全局--组件内部--全局。
各个守卫&钩子的参数,参见:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html