vue - 一文看懂vueRouter路由导航守卫
正如其名,vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
文章目录
导航守卫
正如其名,vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
本篇文章只介绍常用的路由守卫,像beforeResolve
,beforeRouteUpdate
,beforeRouteLeave
这种不常用的不在介绍;感兴趣的可以看一下官网:vue-Router
导航守卫回调参数:
注意:以下介绍的路由守卫里面都会具一个有相同参数的回调函数,如下:
router.beforeEach((to, from,next) => {
// 返回 false 以取消导航
return false
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,每个守卫方法接收三个参数:
-
to: 即将要进入的目标
-
from: 当前导航正要离开的路由
-
next:他是重要的一个参数
1,但凡涉及到有next参数的钩子,必须调用next() 才能继续往下执行下一个钩子,否则路由跳转等会停止。2,如果要中断当前的导航要调用next(false)。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from路由对应的地址。(主要用于登录验证不通过的处理)
3,当然next可以这样使用,next(‘/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。意思是当前的导航被中断,然后进行一个新的导航。可传递的参数与router.push中选项一致。
4,在beforeRouteEnter钩子中next((vm)=>{})内接收的回调函数参数为当前组件的实例vm,这个回调函数在生命周期mounted之后调用,也就是,他是所有导航守卫和生命周期函数最后执行的那个钩子。
5,next(error): (v2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
6,next 在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次, 但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错
1,全局前置守卫(beforeEach )
beforeEach
相当于大门的守卫,每个人(路由)进来之前都要检查一下,看是否符合条件,有权拒绝你进来;
项目中我们经常会在这个守卫中判断用户是否登陆,没有登陆就直接跳到login页面去登陆,已登录过的可能还要检查token是否过期,否则也提示重新登陆,主要代码如下:
注意
next()函数必须要有 否则路由不会跳转,显示空白页;
// 如果想要使用路由守卫 先要配置路由和机型实例化
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
/* 全局前置守卫 */
router.beforeEach((to, from, next) => {
//如果去的是登陆页就直接进
if (to.path == '/login') {
next();
return;
}
//如果去的是其他页面,验证是否有token (说明登录成功) 不然直接跳登录页面
if (localStorage.getItem('token')) {
next();
return;
}
next('/login'); //上面的不过的话 进入login页面
});
2,全局后置守卫(afterEach)
afterEach
是进入某个路由之后触发的钩子函数;通常有以下作用:
1,修改 每个页面的title ,
首先在路由元中meta添加一个title属性,然后 用 document.title=to.meta.title修改当前也买你的title
2,每次切换页面的时候,让页面滚动到最顶部;
代码如下:
/* 全局后置守卫 */
router.afterEach((to,from,nex)=>{
document.title = to.meta.title;// 1,修改当前页面的标题
window.scrollTo(0,0) // 2,每次切换页面的时候,让页面滚动到最顶部
})
3,路由独享守卫 (beforeEnter)
beforeEnter
路由独享守卫是写在每个路由里面的单独函数,每个路由都可以写,只在进入此路由时触发;
通常我们在这个守卫里面判断想要进入此路由的这个人的身份;看符不符合或有没有权限进来;
// 西瓜播放器页面 beforeEnter介绍
{
path: '/xgplayer',
name: 'Xgplayer',
meta: { title: '西瓜播放器' },
component: () => import('../views/xgplayer/xgplayer.vue'),
/* 路由独享守卫 只在进入路由时触发 不想让进可以直接 return false */
beforeEnter: (to, from,next) => {
if (to.path == '/login') {
next()
} else {
alert('请登入');
next('/login')
}
},
},
4,组件内部守卫1(beforeRouteEnter)
beforeRouteEnter
是组件内部的守卫,写法与mounted()周期函数同级;
我经常用来在进入组件的时候来判断是什么路由进来的,并相应的做一些处理;比如取一些缓存数据和请求数据;如下案例:
注意:
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next 来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数;
// 路由钩子函数
beforeRouteEnter(to, from, next) {
let { name } = from;
//判断进来的路由
if (name === "detailsQuery") {
next((vm) => {
let cacheObj = JSON.parse(localStorage.getItem("taskDetailsCache"));
// 如果之前有缓存值 那么给入参赋缓存值 然后请求数据
if (cacheObj) {
vm.cacheObj = cacheObj;
// 开始请求数据
vm.queryParams.taskLevelOne = vm.cacheObj.taskLevelOne;
vm.queryParams.taskLevelTwo = vm.cacheObj.taskLevelTwo;
vm.queryParams.isAbandon = vm.cacheObj.isAssign;
vm.queryParams.status = vm.cacheObj.isStatus;
vm.queryParams.isVisit = vm.cacheObj.isVisit;
// 请求数据
vm.particularsQuery();
}
});
} else {
next(); // 必须要有next() 否则页面不会跳转
}
},
methods:{
particularsQuery(){
...请求接口
}
}
5,组件内部守卫2(beforeRouteUpdate)
未使用过,不在进行介绍;可以直接访问组件实例
this
;
6,组件内部守卫3(beforeRouteLeave)
beforeRouteLeave
在导航离开渲染该组件的对应路由时调用;与beforeRouteUpdate
一样,它也可以直接访问组件实例this
;
这个 离开守卫 通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回 false 来取消。
// 组件内部守卫3
beforeRouteLeave (to, from) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (!answer) return false
}
7,完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。
- 在路由配置里调用 beforeEnter。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫(2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)