vue-router中路由守卫
首先什么是路由守卫呢~
- 官网给出的说法是:导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
- 简单的说,导航守卫就是路由跳转过程中的一些钩子函数。路由跳转是一个大的过程,这个大的过程分为跳转前中后等等细小的过程,在每一个过程中都有一函数,这个函数能让你操作一些其他的事儿的时机,这就是导航守卫。
全局守卫
全局守卫一共有3种:
1.router.beforeEach 全局前置守卫 进入路由之前
2.router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用
3.router.afterEach 全局后置钩子 进入路由之后
使用方法:
// main.js 入口文件
import router from './router'; // 引入路由
router.beforeEach((to, from, next) => {
next();
});
router.beforeResolve((to, from, next) => {
next();
});
router.afterEach((to, from) => {
console.log('afterEach 全局后置钩子');
});
每个守卫方法接收三个参数,分别是
next、to、from
to:即将要进入的目标 路由对象
from:当前导航正要离开的路由
next:function这个参数是个函数,且必须调用,否则不能进入路由(页面空白)。
next()//进入路由(即将要进入的目标 路由对象)
next(false)//终断并取消进入该路由,假如url发生变化,会把地址重置到from路由对应的地址(也就是将要离开的路由地址)
next(error)//2.4.0之后新增,该导航会终止且该错误会被传递给 router.onError() 注册过的回调。
next('/xxx')//路由跳转到指定导航,路由被中断,进入新的导航
注意:当你使用next('/xxx')或者next({path:''})或者next({name:''})的时候
一定要设置诸如 replace: true、name: 'home' 之类的选项,以及任何用在
router-link 的 to prop 或 router.push 中的选项。
全局解析守卫
在2.5.0新增了router.beforeResolve(全局解析守卫)
他和 router.beforeEach 类似,他俩唯一的区别是在导航被确认之前,同时所有的组件被解析后(包括异步组件)会被调用
全局后置钩子
基本不用~全局后置钩子不会接受next更不会改变路由
路由独享守卫
假如你不想设置全局路由或者想单独某个路由单独设置,那么你可以为他进行单独设置
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// 直接在路由中设置,参数什么的都是一样的
}
}
]
})
组件内的守卫
beforeRouteEnter:不能访问到this
beforeRouteUpdate (2.2 新增):可以访问this
beforeRouteLeave:可以访问this
官网给出的说法是
钩子的一些知识
路由钩子函数的错误捕获
- 如果我们在全局守卫/路由独享守卫/组件路由守卫的钩子函数中有错误,可以这样捕获:
router.onError(callback => {
// 2.4.0新增 并不常用,了解一下就可以了
console.log(callback, 'callback');
});
//在路由文档中还有更多的实例方法:动态添加路由等,有兴趣可以了解一下。
//跳转死循环,页面永远空白
//我了解到的,很多人会碰到这个问题,来看一下这段伪代码:
router.beforeEach((to, from, next) => {
if(登录){
next()
}else{
next({ name: 'login' });
}
});
- 看逻辑貌似是对的,但是当我们跳转到login之后,因为此时还是未登录状态,所以会一直跳转到login然后死循环,页面一直是空白的,所以:我们需要把判断条件稍微改一下。
if(登录 || to.name === 'login'){ next() } // 登录,或者将要前往login页面的时候,就允许进入路由
//全局后置钩子的跳转:
//文档中提到因为router.afterEach不接受next函数所以也不会改变导航本身,意思就是只能当成一个钩子来使用,但是我自己在试的时候发现,我们可以通过这种形式来实现跳转:
// main.js 入口文件
import router from './router'; // 引入路由
router.afterEach((to, from) => {
if (未登录 && to.name !== 'login') {
router.push({ name: 'login' }); // 跳转login
}
});
额,通过router.beforeEach 也完全可以实现且更好,我就骚一下。
完整的路由导航解析流程(不包括其他生命周期):
1. 触发进入其他路由。
2. 调用要离开路由的组件守卫beforeRouteLeave
3. 调用局前置守卫:beforeEach
4. 在重用的组件里调用 beforeRouteUpdate
5. 调用路由独享守卫 beforeEnter。
6. 解析异步路由组件。
7. 在将要进入的路由组件中调用beforeRouteEnter
8. 调用全局解析守卫 beforeResolve
9. 导航被确认。
10. 调用全局后置钩子的 afterEach 钩子。
11. 触发DOM更新(mounted)。
12. 执行beforeRouteEnter 守卫中传给 next 的回调函数