vue-router实现根据用户权限显示不同菜单-动态路由

本文介绍了前端根据用户权限动态生成路由的解决方案。在用户登录后,前端通过后端返回的权限表遍历路由,使用vue-router的addRoutes方法动态添加权限路由。同时,实现了未登录用户无法直接访问特定路由的逻辑,确保了权限控制的安全性。
摘要由CSDN通过智能技术生成

一,情景再现

做前端开发的同学,大多都遇到过这种需求:页面菜单根据用户权限动态生成,一个常见的解决方案是:
前端初始化的时候,只挂载不需要权限路由,如登陆,注册等页面路由,然后等用户登录之后,后端返回当前用户的权限表,前端根据这个权限表遍历前端路由表,动态生成用户权限路由,然后使用vue-router提供的addRoutes,将权限路由表动态添加到路由实例中,整个过程大致如下:

import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '@/store'
import axios from 'axios'
import baseAPIs from '@/api/common'
import { Message } from 'element-ui'

// 引入组件
const login = () => import('@/views/login/index.vue') // 登录页

Vue.use(VueRouter)
//避免vue-router在3.0版本以上重复点击菜单报错的问题
const originalPush = VueRouter.prototype.push
   VueRouter.prototype.push = function push(location) {
   return originalPush.call(this, location).catch(err => err)
}

let routes = [            //先把基本的登陆路由写好
  	{
    	path: '/',
    	redirect: '/login',
    	hidden: true,
  	},
  	{
    	path: '/login',
    	component: login,
    	name: '登录',
    	hidden: true,
	},
]

let router = new VueRouter({
    routes
})

/**
 * 判断当前是否登录,未登录不能跳转路由
 * 防止未登录状态下直接输入路由跳转
 */
/* eslint-disable no-new */
router.beforeEach((to, from, next) => {
    if (to.path == '/login') {
		localStorage.removeItem('USERINFO')
		next()
    }else{
		if (!JSON.parse(localStorage.getItem('USERINFO'))) {
			next({
				path: '/login'          
			})
			next()
		} else { // 登录成功
			// 如果资源为空得话
			if (store.state.common.menus.length == 0) {
				// 请求资源,生成动态路由
				let url = `${baseAPIs.serverOne}/B2CMainPlat_13_SLHZ?CCB_IBSVersion=V6&PT_STYLE=1&PT_LANGUAGE=CN&TXCODE=VAUM99`
				let params = { 
					txnFcnNo: '1', 
					token: localStorage.getItem('USERINFO')?JSON.parse(localStorage.getItem('USERINFO')).token:''
				}
				axios.get(url,{params: params}).then(response => {
					if (response.data.CODE == 3){
						Message({
							message: response.data.MSG,
							type: 'error',
							duration: 3 * 1000,
						})
						setTimeout(()=>{
							router.push({ path: '/login' })
							location.reload()
						},1000)
					} else {
						store.state.common.menus = response.data.MENUS   //也就是说,不同权限的用户登陆,所返回展示的路由菜单是不一样的
						getRouters(response.data.MENUS)  //设置路由
						addComps(rts)   //在路由中懒加载对应要渲染的组件
						let homeRts = [{
							path: '/home',
							component: (resolve) => require(['@/views/home/index.vue'], resolve),
							children: [...rts,     //从后台获取到的动态路由,展开后作为home页面的二级路由
								{ path: '', redirect: rts[0].path },
								{ path: 'consumeRule/couponDetail', name: '优惠券管理', component: resolve => require(['@/views/consumeRule/pages/couponDetail.vue'], resolve) },
								{ path: 'error', name: '错误', component: resolve => require(['@/views/error/index.vue'], resolve) },
							]   //这三个是基本的都会有的路由和菜单
						}]
						router.addRoutes(homeRts)   //将后台返回并配置好的路由,添加到路由配置中去,也就是home路由是和login并列的
					}
				}).catch(error => {
					console.log(error)
				})
			}
			next()
		}
	}
})

let rts = []
const getRouters = (menus) => {
    for (let i = 0; i < menus.length; i++) {
        if (menus[i].type == 1) {
            let rt = {
                name: menus[i].name,
                path: menus[i].url
			}
			store.state.common.paths.push('/home/'+menus[i].url)    //这里同样报错动态路由的url
            rts.push(rt)            //这里就将每个菜单的路由push进去了
		}
		if (menus[i].permission) {    //查看本菜单,该登陆用用户的权限,
			store.state.common.userInfo.permissions.push(menus[i].permission)   
			//有权限,就把所有该用户的权限保存起来,到时候该用户发请求,就利用这个判断该用户是否有权限完成该操作
		}
        if (menus[i].children && menus[i].children.length > 0) {  //当存在子菜单时
            getRouters(menus[i].children)  //递归实现子菜单的路由设置
        }
    }
}
//路由懒加载对应的渲染组件
const addComps = (routres) => {
    return routres.forEach(rt => {
        rt.component = (resolve) => require([`@/views/${rt.path}`], resolve)
    })
}

export default router

二,原理解析

在这里插入图片描述

在这里插入图片描述
对应的vuex中存储的:
在这里插入图片描述

  • 18
    点赞
  • 139
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值