导航守卫,顾名思义就是在给导航加了一层保障,更通俗一点,就是需要在调用导航之前,先进行验明身份,如果通过了,就可以调用导航,如果没通过,将会被拒绝调用
这种导航守卫一般会用在验证登录,尤其是在单页面前端配置路由的情况下,我们通产会在前端会有登录页,如果不做导航守卫,我们直接在地址栏手动输入路由,很可能会造成还没有登录就可以进入主页的BUG,所有对此我们要在路由跳转之前验证是否登录,也就是导航守卫
先看官方文档:
全局守卫
你可以使用 注册一个全局前置守卫:
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
每个守卫方法接收三个参数:
: 即将要进入的目标 路由对象
: 当前导航正要离开的路由
: 一定要调用该方法来resolve这个钩子。执行效果依赖 方法的调用参数。
: 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是confirmed(确认的)。
: 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 路由对应的地址。
或者: 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 传递任意位置对象,且允许设置诸如 、 之类的选项以及任何用在 的 prop 或 中的选项。
: (2.4.0+) 如果传入 的参数是一个 实例,则导航会被终止且该错误会被传递给 注册过的回调。
确保要调用 方法,否则钩子就不会被 resolved。
从文档我们可以看出,全局导航是作用在router文件夹下的全局对象上的,以前我们经常会后的
export default new Router({
...
})
现在我们不要直接匿名导出router了
const router = new Router();
export default router;
这个时候我们就可以对router进行导航守卫了
我们按照官方文档尝试做一个导航守卫
router.beforeEach是在导航地址将要改变的时候触发的,如果我们用来做验证登录,我们想要达到的效果是:
如果用户登录了,导航就随着用户点击而跳转;如果用户没跳转,导航就跳转到login页面,这个时候我们就需要进行判定
如果登录了,isLogin是true,点击就可以进行下一钩子函数
但是如果没有登录,这里就出现了问题,程序进入了死循环,不停的执行
next('/login'),知道栈溢出,就像这样
造成这种情况到底是哪里出了问题呢?思前想后逻辑并没有什么问题呀?是写法有问题吗?
原因是这样:
next()直接跳转到to.path路径,没有再执行一遍beforeEach导航钩子,next('/')或者next('/login')自己指定路径的,路由跳转的时候还执行一遍beforeEach导航钩子,所以上面出现死循环;
因为next('/login')跳转路径之后会重新调用一次beforeEach函数,这个时候我们还会运行next('login'),然后又会进入beforeEach,这样就进入了死循环,所以程序我们可以这样写
内部没有参数的next()是唯一出口
内部没有参数的next()是唯一出口
内部没有参数的next()是唯一出口
重要的事情说三遍
在生产中我们还会遇到这种情况,在未登录之前有些页面是可以跳转的,有些页面是无法跳转的,而登录之后是都可以跳转的,这种情况我们可以这样处理:
放入数组内的是未登录可见的,不在数组内的会提示登录访问,这样就达到了我们想要的效果
领取专属 10元无门槛券
私享最新 技术干货