分类

按执行的时机,定义的位置

组件内的守卫

注意: 这里描述的不是任意组件,而是路由级别的组件

代码:

  1. // 定义在组件内部的
  2. beforeRouteEnter(to, from, next) {
  3. // 在渲染该组件的对应路由被 confirm 前调用
  4. // 不!能!获取组件实例 `this`
  5. // 因为当守卫执行前,组件实例还没被创建
  6. },
  7. beforeRouteUpdate(to, from, next) {
  8. },
  9. beforeRouteLeave(to, from, next) {
  10. }

路由独享守卫

注意:在路由配置上直接定义 beforeEnter 守卫

代码:

  1. const router = new VueRouter({
  2. routes: [
  3. {
  4. path: '/foo',
  5. component: Foo,
  6. beforeEnter: (to, from, next) => {
  7. // ...
  8. }
  9. }
  10. ]
  11. })

全局守卫

说明: 是router对象一个属性,本质上是一个函数。在路由切换时,它会被调用,用它就可

以用来去检查凭证(是否登录)。

代码:

  1. const router = new VueRouter({ ... })
  2. router.beforeEach(function (to, from, next) {
  3. console.log('路由变化了', to, from, next)
  4. next()
  5. })
  6. router.afterEach(function (to, from) {
  7. console.log('路由变化了', to, from)
  8. })

路由守卫的参数说明:

  1. <br />![](https://cdn.nlark.com/yuque/0/2021/jpeg/21762447/1623858237892-9e5db2e9-6fdd-4dc5-8072-304072cbaae2.jpeg)<br />

应用场景

场景1: 离开页面时,阻止跳转

  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)

代码演示:

  1. beforeRouteLeave (to, from, next) {
  2. if (this.msg && window.confirm('确定要跳转')) {
  3. next() // 如果用户确定要跳转,就放行
  4. } else {
  5. next(false) // 如果用户不确定跳转,就不跳转
  6. }
  7. }

场景2: 动态路由跳转

  1. ** 比如: 文章详情页(跳转的时候需要携带参数的 /foo/:id,在 /foo/1 /foo/2 之间跳转的时**<br />** 候)**

代码演示:

  1. beforeRouteUpdate(to, from, next) {
  2. next()
  3. this.加载详情()
  4. }

另外说明:

  1. 如果外面已经定义了一个created钩子函数,里面也是放的是this.加载详情(), 然后又用到了这个路由守卫 <br /> 的话,如果不在里面再调用一次this.加载详情(), 跳转的时候只是地址栏里面的变化了,页面是还没有跳转的, <br /> 因为在created里面详情页组件已经被创建了

场景3: 权限校验

定义在全局守卫

情况1:如果一个用户没有登陆(没有token值),他还想去访问个人中心页,让他回去登录页

图示说明:

  1. ![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. 1. 如果没有登陆就不能访问某些敏感页面<br /> 2. 如果登陆了,就不能再访问login页面
  1. import store from '@/store/index.js'
  2. const vipList = ['/setting']
  3. router.beforeEach((to, from, next) => {
  4. const token = store.state.tokenInfo.token
  5. console.log(token)
  6. if (!token && vipList.includes(to.path)) {
  7. console.log('没有权限,不能访问vip页面')
  8. next('/login)
  9. } else if (token && to.path === '/login') {
  10. console.log('已经登录了,就不能访问login了')
  11. next('/')
  12. } else {
  13. next()
  14. }
  15. })
  16. export default router

注意:

  1. 获取token动作应该在每次路由跳转都去做(代码要写在beforeEach内)<br /> 把需要权限的页面写在一个数组中,方便我们使用includes方法进行判断

情况2: 从a页面出发,访问b页面,发现没有权限,路由守卫转跳到login页中,在login中登录成功之后,应该要跳转到哪里呢?

代码演示:

  1. router.beforeEach((to, from, next) => {
  2. const token = store.state.tokenInfo.token
  3. console.log(token)
  4. if (!token && vipList.includes(to.path)) {
  5. console.log(to.fullPath)
  6. // 用户想访问b页面,但是没登录就转到登录,登录了以后不是跳到主页,还是跳到想去的b页面
  7. next('/login?backto=' + encodeURIComponent(to.fullPath))
  8. } else if (token && to.path === '/login') {
  9. next('/')
  10. } else {
  11. next()
  12. }
  13. })

关键代码:

  1. 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)


  1. <br /> <br /> <br />** **<br />