74 路由守卫
路由守卫在开发者中的也是特别多的,主要是对路由进行权限控制,分为全局守卫、独享守卫、组件内守卫,下面一一根据案例说明
比如说有的路由不是随便看的,需要登录之后才可以看,比如说淘宝的个人中心,肯定是登录之后才能看的,下面进行简单演示
现在需要验证身份,这里我存在localstorage里面一个简单的数据作为验证凭证,如果name为zhangsan,才能查看news和message的路由信息,不然是查看不了的
当然也可以存在vuex中,或者是缓存,实际开发中有时候也会是用户的token
想要实现这种需求,最好的方式就是去router路由器中配置规则,这时候就不能直接暴露了,不然无法增加校验规则
全局守卫
它分为前置和后置两种守卫
前置路由守卫(beforeEach)
它是router中的一个方法,在初始化的时候和每次路由切换之前被调用
可以看到初始化和点击切换路由都会进行函数执行
但是没跳到路由对于的页面,这时候需要知道它的三个参数,分别是to,from,next
to(去哪)
from(从哪来)
next(放行)
如果需要放行,加上next()即可
这就是从哪来到哪去以及路由放行
动态放行
接下来就可以通过是否放行的标志进行动态放行了,一般从服务器获取,这里做演示写的比较简单从localStorage获取校验了
这里我故意让两个参数对不上不放行
这样怎么点路由也不会跳转了
但是这样太暴力了,我想要更精细的路由判断,那么可以这么做
精准校验路由
通过这种方式,可以放行一些路由和对指定路由进行控制,而不是全部路由
不想用路径当然可以用name去判断
// 全局前置路由守卫 在初始化的时候和每次路由切换之前被调用 router.beforeEach((to,from,next)=>{ if(to.path==='/home/news' || to.path==='/home/message'){ // 如果从localStorage获取到的name为zhangsan就放行 if(localStorage.getItem('name')==='zhangsan1'){ next() }else{ alert('参数校验失败,无权限查看') } }else{ next() } })
前置路由一个问题就是如果要对多个路由进行拦截,那么需要写很多个判断
这样就会显得非常麻烦,针对这种情况,我们可以给每一个路由里面定义一个属性,如果为真就需要校验权限,为假就放行
但是这种方式加了也没用,路由的配置都是写死的,不是想加什么就能加的
meta(路由元信息)属性判断校验
如果真的想加自定义的属性,可以放在meta里面,meta里面专门准备了一个容易供我们存自定义数据信息,一般是键值对,多个属性使用逗号隔开
这样就可以把参数放到需要校验的路由里面了,如果不需要校验可以直接不写
这样的写法相对来说更简单
后置路由守卫(afterEach)
既然有前置路由,那么相对的也有后置路由,在初始化的时候和每次路由切换之后被调用,它也有to和from并且和前置守卫的作用是一样的,区别就是前置路由有next,后端路由主要是做切换后的工作
改变页签效果
这时候我想要加一个功能,点击哪个路由会把对应的页签也换成这个路由的名称我们
首先要给每一个路由增加对应的页签名称,可以存放到meta里面,这时候用后置路由实现最合适不过,但是最好把index.html里面的title名称也改掉
独享路由守卫(beforeEnter)
顾名思义就是某一个路由单独享用的守卫,它同样会收到to,from,next三个参数,逻辑和全局守卫一样
比如只想对news路由做出限制,其他的路由不管
值得注意的是它是配置路由里面的一个属性,并且它只有前置没有后置,独享的前置路由守卫和全局的后置路由守卫可以配合使用
功能其实和全局守卫是一样的,只不过全局路由守卫可以控制多个,而它只能控制一个
组件内路由守卫
这是最好一种路由守卫,和前面几种都不同,它是在组件里面去写的路由守卫,而不是在路由配置文件里面写的路由守卫,可以说这种路由守卫是独享路由守卫和全局守卫的结合体,只不过是在组件里面编写的
这种路由守卫使用的场景比较少,如果想在组件里面写点这个组件独有的逻辑,可以借助这种守卫,组件内路由守卫也是可以和全局后置守卫互用的
beforeRouteEnter(进入守卫)
路由进入之前 通过路由规则进入该组件时被调用,可以把全局前置路由那一套鉴权规则写道这里面
beforeRouteLeave(离开守卫)
路由进入之后 通过路由规则离开该组件时被调用
总结
- 作用:对路由进行权限控制
- 分类:全局守卫、独享守卫、组件内守卫
- 全局守卫:
//全局前置守卫:初始化时执行、每次路由切换前执行 router.beforeEach((to,from,next)=>{ console.log('beforeEach',to,from) if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制 if(localStorage.getItem('school') === 'atguigu'){ //权限控制的具体规则 next() //放行 }else{ alert('暂无权限查看') // next({name:'guanyu'}) } }else{ next() //放行 } }) //全局后置守卫:初始化时执行、每次路由切换后执行 router.afterEach((to,from)=>{ console.log('afterEach',to,from) if(to.meta.title){ document.title = to.meta.title //修改网页的title }else{ document.title = 'vue_test' } })
- 独享守卫:
beforeEnter(to,from,next){ console.log('beforeEnter',to,from) if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制 if(localStorage.getItem('school') === 'atguigu'){ next() }else{ alert('暂无权限查看') // next({name:'guanyu'}) } }else{ next() } }
- 组件内守卫:
//进入守卫:通过路由规则,进入该组件时被调用 beforeRouteEnter (to, from, next) { }, //离开守卫:通过路由规则,离开该组件时被调用 beforeRouteLeave (to, from, next) { }