分类
按执行的时机,定义的位置
组件内的守卫
注意: 这里描述的不是任意组件,而是路由级别的组件
代码:
// 定义在组件内部的
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
},
beforeRouteLeave(to, from, next) {
}
路由独享守卫
注意:在路由配置上直接定义 beforeEnter 守卫
代码:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
全局守卫
说明: 是router对象一个属性,本质上是一个函数。在路由切换时,它会被调用,用它就可
以用来去检查凭证(是否登录)。
代码:
const router = new VueRouter({ ... })
router.beforeEach(function (to, from, next) {
console.log('路由变化了', to, from, next)
next()
})
router.afterEach(function (to, from) {
console.log('路由变化了', to, from)
})
路由守卫的参数说明:
<br />![](https://cdn.nlark.com/yuque/0/2021/jpeg/21762447/1623858237892-9e5db2e9-6fdd-4dc5-8072-304072cbaae2.jpeg)<br />
应用场景
场景1: 离开页面时,阻止跳转
![image.png](https://cdn.nlark.com/yuque/0/2021/png/21762447/1623857659382-eb80809e-cd82-47d9-8ab6-4421e5b0bd41.png#clientId=uc501e541-cf15-4&from=paste&height=255&id=u25280ae6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=255&originWidth=635&originalType=binary&ratio=1&size=27068&status=done&style=none&taskId=uede0fa51-7291-464f-aa65-da8902ebcd9&width=635)
代码演示:
beforeRouteLeave (to, from, next) {
if (this.msg && window.confirm('确定要跳转')) {
next() // 如果用户确定要跳转,就放行
} else {
next(false) // 如果用户不确定跳转,就不跳转
}
}
场景2: 动态路由跳转
** 比如: 文章详情页(跳转的时候需要携带参数的 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时**<br />** 候)**
代码演示:
beforeRouteUpdate(to, from, next) {
next()
this.加载详情()
}
另外说明:
如果外面已经定义了一个created钩子函数,里面也是放的是this.加载详情(), 然后又用到了这个路由守卫 <br /> 的话,如果不在里面再调用一次this.加载详情(), 跳转的时候只是地址栏里面的变化了,页面是还没有跳转的, <br /> 因为在created里面详情页组件已经被创建了
场景3: 权限校验
定义在全局守卫
情况1:如果一个用户没有登陆(没有token值),他还想去访问个人中心页,让他回去登录页
图示说明:
![image.png](https://cdn.nlark.com/yuque/0/2021/png/21762447/1623860493736-b699eca7-d2a5-4058-bade-c0a28390c4e5.png#clientId=uc501e541-cf15-4&from=paste&height=246&id=ucc47f915&margin=%5Bobject%20Object%5D&name=image.png&originHeight=246&originWidth=570&originalType=binary&ratio=1&size=31620&status=done&style=none&taskId=uaff8836e-869c-4824-9f55-5d1c78dc19d&width=570)
代码演示:
在router/index.js中补充一个前置路由守卫。
需求:
1. 如果没有登陆就不能访问某些敏感页面<br /> 2. 如果登陆了,就不能再访问login页面
import store from '@/store/index.js'
const vipList = ['/setting']
router.beforeEach((to, from, next) => {
const token = store.state.tokenInfo.token
console.log(token)
if (!token && vipList.includes(to.path)) {
console.log('没有权限,不能访问vip页面')
next('/login)
} else if (token && to.path === '/login') {
console.log('已经登录了,就不能访问login了')
next('/')
} else {
next()
}
})
export default router
注意:
获取token动作应该在每次路由跳转都去做(代码要写在beforeEach内)<br /> 把需要权限的页面写在一个数组中,方便我们使用includes方法进行判断
情况2: 从a页面出发,访问b页面,发现没有权限,路由守卫转跳到login页中,在login中登录成功之后,应该要跳转到哪里呢?
代码演示:
router.beforeEach((to, from, next) => {
const token = store.state.tokenInfo.token
console.log(token)
if (!token && vipList.includes(to.path)) {
console.log(to.fullPath)
// 用户想访问b页面,但是没登录就转到登录,登录了以后不是跳到主页,还是跳到想去的b页面
next('/login?backto=' + encodeURIComponent(to.fullPath))
} else if (token && to.path === '/login') {
next('/')
} else {
next()
}
})
关键代码:
1.在跳到登录页时,传入要返回的页面地址 : <br /> ![image.png](https://cdn.nlark.com/yuque/0/2021/png/21762447/1623862076175-7d107b6a-54ee-416c-8723-02dc4bf8749c.png#clientId=uc501e541-cf15-4&from=paste&height=40&id=u2b14bbcd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=40&originWidth=348&originalType=binary&ratio=1&size=1958&status=done&style=none&taskId=u0dc6007e-52cf-479f-97f7-bbafff8a23e&width=348) to.fullPath会包含路径中的查询参数(/setting?a=1)<br /> 2. 登陆成功后,回到初始页面:<br /> ![image.png](https://cdn.nlark.com/yuque/0/2021/png/21762447/1623862214527-7076d418-c6b0-484a-adf2-3143735d8491.png#clientId=uc501e541-cf15-4&from=paste&height=127&id=ud90eea62&margin=%5Bobject%20Object%5D&name=image.png&originHeight=127&originWidth=319&originalType=binary&ratio=1&size=7367&status=done&style=none&taskId=u1a552b0c-b583-44f9-a7ed-96cd4e3e487&width=319)
<br /> <br /> <br />** **<br />