• 十一、【Vue-Router】路由守卫


    十一、路由守卫

    本文记录 5 个守卫:

    1. 全局守卫 2 个
      1. beforeEach:全局前置路由守卫
      2. afterEach:全局后置路由守卫
    2. 私有守卫 1 个
      1. beforeEnter:路由私有守卫
    3. 组件内守卫 2 个
      1. beforeRouteEnter:进入当前组件时调用
      2. beforeRouteLeave:离开当前组件时被调用

    1、需求

    Others 和 Home 人人都可访问, News 和 Message 必须是登录的用户才能访问


    2、功能一览

    在这里插入图片描述


    3、思考一波

    需求就是加权限,权限怎么加合适呢?

    在路由跳转的时候加最合适,那应该怎么加呢?

    挂上拦截器在路由跳转的时候拦截检查,那这个所谓的拦截器是什么呢?

    全局前置-路由守卫 beforeEach


    4、全局前置-路由守卫 beforeEach

    1、router/index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import Others from '../views/Others'
    import Home from '../views/Home'
    import News from '../views/News'
    import Message from '../views/Message'
    import Details from '../views/Details'
    
    //创建一个路由器
    const router =  new VueRouter({
    	routes:[ // 路由器管理的是什么呀?肯定是路由啊,全在这了!
    		{ // 一级路由
    			name: 'other',
    			path: '/others',
    			component: Others
    		},
    		{ // 一级路由
    			path: '/home',
    			component: Home,
    			children:[ // 为什么是数组?你凭什么断定他就只能生一个娃?
    				{ // 二级路由
    					name: 'news',
    					path: 'news', // 数组里的就不用加'/'了,路由器遍历的时候自动加上了
    					component: News,
    				},
    				{ // 二级路由
    					name: 'message',
    					path: 'message',
    					component: Message,
    					children: [
    						{ // 三级路由
    							name: 'detail',
    							path: 'details/:id/:title/:desc', // 配置占位符
    							component: Details,
    							props(route){ // router每次调的时候会把 $route 传进来,你想怎么取就怎么取!
    								return {
    									id: route.params.id,
    									title: route.params.title,
    									desc: route.params.desc
    								}
    							}
    						},
    					]
    				}
    			]
    		}
    	]
    })
    
    // 全局前置路由守卫(初始化和每次路由跳转之前调用)
    router.beforeEach((to, from, next)=>{
    	console.log('to===>', to)
    	console.log('from===>', from)
    	console.log('next===>', next)
    	next()
    })
    
    // 暴露路由器
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    2、Result

    在这里插入图片描述


    5、优化 beforeEach

    1、router/index.js

    // 创建一个白名单
    const whiteList = ['/others', '/home']
    
    // 全局前置路由守卫(初始化和每次路由跳转之前调用)
    router.beforeEach((to, from, next)=>{
    	// 白名单直接放行
        if(whiteList.includes(to.path)){
            next()
        } else if(sessionStorage.getItem('id')){ // 是否登录,登录了会把id存到sessionStorage
            next()
    	} else {
    		alert('暂无权限!')
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2、Result

    在这里插入图片描述


    6、另一种思路:路由元数据 meta

    我可不可以在配置路由的时候给每个路由挂个boolean类型参数peiqi,我在守卫里只要判断每个to的peiqi的真假就决定是否放行?请参观to的属性:

    在这里插入图片描述


    7、践行新思路

    router/index.js

    // ...
    //创建一个路由器
    const router =  new VueRouter({
    	routes:[ // 路由器管理的是什么呀?肯定是路由啊,全在这了!
    		{ // 一级路由
    			name: 'other',
    			path: '/others',
    			component: Others,
                meta: {
                    peiqi: true
                }
    		},
    		{ // 一级路由
    			path: '/home',
    			component: Home,
                meta: {
                    peiqi: true
                }
    			children:[ 
                    // ... 其余的不配meta
    			]
    		}
    	]
    })
    
    // 全局前置路由守卫(初始化和每次路由跳转之前调用)
    router.beforeEach((to, from, next)=>{
    	// 有peiqi且为true的放行!
        if(to.meta.peiqi){
            next()
        } else if(sessionStorage.getItem('id')){ // 是否登录,登录了会把id存到sessionStorage
            next()
    	} else {
    		alert('暂无权限!')
    	}
    })
    
    // 暴露路由器
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    8、全局后置-路由守卫 afterEach

    有前置守卫,必然就有后置守卫!

    这里提出新需求:每次跳转后页签标题要和当前组件契合

    1、router/index.js

    // ...
    //创建一个路由器
    const router =  new VueRouter({
    	routes:[
    		{
    			name: 'other',
    			path: '/others',
    			component: Others,
                meta: {
                    peiqi: true,
                    title: '其他'
                }
    		},
    		{
    			path: '/home',
    			component: Home,
                meta: {
                    peiqi: true,
                    title: '主页'
                }
    			children:[ 
                    // ... 其余的meta也配title,但是篇幅过长自行体会
    			]
    		}
    	]
    })
    
    // ... 略
    
    // 全局后置路由守卫(初始化和每次路由跳转之后调用)
    // 后置没有next参数,走到这说明前置守卫已经放行,这里不再多此一举
    router.afterEach((to, from)=>{
    	document.title = to.meta.title || 'Mr.Wang!'
    })
    
    // 暴露路由器
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    2、Result

    在这里插入图片描述


    9、独享路由守卫 beforeEnter

    有全局的就有独享的,没错就是 beforeEnter!(注意!独享守卫只有前置,没有后置!)

    执行顺序:beforeEach–>beforeEnter–>afterEach

    这里提出新需求:跳转到 Others 的时候 title 改为 佩奇!

    这里有大聪明就想问了,我直接把 Others 路由的 meta.title 改成 " 佩奇 " 不就得了吗?

    咋滴,你就不想学 beforeEnter 了呗?

    1、router/index.js

    // ...
    //创建一个路由器
    const router =  new VueRouter({
    	routes:[
    		{
    			name: 'other',
    			path: '/others',
    			component: Others,
                meta: {
                    peiqi: true,
                    title: '其他'
                },
                // 独享路由守卫
                beforeEnter(to, from, next){
    				to.meta.title = '佩奇!'
                    next()
                }
    		},
            // ... 略
    	]
    })
    // ... 略
    // 暴露路由器
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2、Result

    在这里插入图片描述


    10、组件内路由守卫 beforeRouteEnter/beforeRouteLeave

    1. beforeRouteEnter:通过路由规则进入该组件时调用
    2. beforeRouteLeave:通过路由规则离开该组件时调用

    需求:我想在进入 Others 时开启一个定时,离开时关闭定时

    1、测试

    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2、Result

    在这里插入图片描述

    3、分析一波

    beforeRouteEnter 里 this 未定义,那该如何操作当 vc 呢?

    没错就是在 next 回调,参数就是当前 vc 实例!

    4、CODE

    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    5、Result

    在这里插入图片描述


    11、路由守卫总结

    1. 作用:对路由进行权限控制

    2. 分类:全局守卫、独享守卫、组件内守卫

    3. 全局守卫:

      //全局前置守卫:初始化时执行、每次路由切换前执行
      router.beforeEach((to,from,next)=>{
         console.log('beforeEach',to,from)
         if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
            if(sessionStorage.getItem('id')){ //权限控制的具体规则
               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'
         }
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    4. 独享守卫:

      beforeEnter(to,from,next){
         console.log('beforeEnter',to,from)
         if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
            if(localStorage.getItem('id')){
               next()
            }else{
               alert('暂无权限查看')
            }
         }else{
            next()
         }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    5. 组件内守卫:

      //进入守卫:通过路由规则,进入该组件时被调用
      beforeRouteEnter (to, from, next) {
      },
      //离开守卫:通过路由规则,离开该组件时被调用
      beforeRouteLeave (to, from, next) {
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
  • 相关阅读:
    在Linux部署Docker并上传静态资源(快速教程)
    【计算机网络笔记】数据交换之报文交换和分组交换
    即席查询Kylin
    (附源码)spring boot大学生综合素质测评系统 毕业设计 162308
    spark中的shuffle简述 那些会导致shuffle的算子
    适用于音视频的弱网测试整理
    从408改考自主命题,211贵州大学考研改考
    微信小程序——简易复制文本
    C语言学习笔记(十五)
    DispatcherServlet是如何进行初始化的呢?
  • 原文地址:https://blog.csdn.net/qq_30769437/article/details/126217496