vue 菜单级别权限控制实现

之前写了一篇 《vue 按钮级别权限控制实现》,里面介绍了前端页面对于按钮权限的控制,这一篇来说说前端页面对于菜单权限的控制。

前端菜单权限,就是根据用户的权限不同控制菜单的显示隐藏,不同的场景,实现的方式也有所不同。

一、前端控制路由

前端配置好一套通用路由表一套动态路由表,然后获取用户权限数据,根据权限数据对比动态路由表,生成具有用户权限的新路由表,然后使用 router.addRoutes方法将新路由表动态挂载到 router 上,最后根据路由表渲染菜单。

实现如下:
1、在 route.js 里面配置通用的路由(404,login 等)。

import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
const router = new Router({
    
    
  mode: 'hash',
  routes:[{
    
    
  		path:'/',
		redirect:'/login'
  },{
    
    
		path:'/login',
		name:'login',
		component: () => import('../view/login')
	},{
    
    
		path:'/404',
		name:'404',
		component: () => import('../view/404')
	}]
})
export default router;

2、新建一个 routerList.js 文件,里面配置好动态路由表;通过 isShow 字段控制菜单的显示隐藏。

const routerList = [{
    
    
		path:'/',
		name:'home',
		component: () => import('../view/index.vue'),
		meta:{
    
    
			title:'Home'
		},
		children:[{
    
    
			path:'menu1',
			name:'menu1',
			isShow:true,
			component: () => import('../view/menu1.vue'),
			meta:{
    
    
				title:'菜单1',
				icon:'el-icon-info'
			}
		},{
    
    
			path:'menu2',
			name:'menu2',
			isShow:true,
			component: () => import('../view/menu2.vue'),
			meta:{
    
    
				title:'菜单2',
				icon:'el-icon-info'
			}
		},{
    
    
			path:'menu3',
			name:'menu3',
			isShow:true,
			component: () => import('../view/menu3.vue'),
			meta:{
    
    
				title:'菜单3',
				icon:'el-icon-info'
			}
		}]	
	}
]

3、获取接口返回权限数据。

//以数组为例
['menu1','menu3']

4、根据这个数组来处理已有的动态路由表,将数组里没有的菜单对应动态路由表里的路由的 isShow 属性值改为 false;生成的新路由表保存到 vuex 和 localStorage 里面。

const routerList = [{
    
    
		path:'/',
		name:'home',
		component: () => import('../view/index.vue'),
		meta:{
    
    
			title:'Home'
		},
		children:[{
    
    
			path:'menu1',
			name:'menu1',
			isShow:true,
			component: () => import('../view/menu1.vue'),
			meta:{
    
    
				title:'菜单1',
				icon:'el-icon-info'
			}
		},{
    
    
			path:'menu2',
			name:'menu2',
			isShow:false,
			component: () => import('../view/menu2.vue'),
			meta:{
    
    
				title:'菜单2',
				icon:'el-icon-info'
			}
		},{
    
    
			path:'menu3',
			name:'menu3',
			isShow:true,
			component: () => import('../view/menu3.vue'),
			meta:{
    
    
				title:'菜单3',
				icon:'el-icon-info'
			}
		}]	
	}
]

4、在 App.vue 文件的 created 生命周期使用 addRouters 方法将通过权限数据处理过的最新路由表加入到 router 里面去。

//处理好数据之后
this.$router.options.routes = routerList;
this.$router.addRoutes(routerList);

5、在路由切换时,通过路由守卫判断当前将要跳转的页面是否有权限,有正常跳转,没有则跳转到 404 页面。

router.beforeEach((to, from, next) => {
    
    
  if (to.path === '/login') {
    
    
    next();
  } else if (to.path === '/404') {
    
    
      next();
  } else {
    
    
        let resstr = ['menu1','menu3'];
        if (resstr != 'null' && resstr != undefined) {
    
    
          let hasPermiss = resstr.find(item => {
    
    
              return item.includes(to.path.split('/')[to.path.split('/').length-1]);
          })
          if (hasPermiss) {
    
    
            next();
          } else {
    
    
            next({
    
    path: '/404'});
          }
        }
    }
})

6、在菜单页面,使用 this.$router.options.routers 来获取最新路由对象,通过 v-for 循环渲染菜单栏,isShow 属性值为 false 的菜单不显示。

二、后端控制路由

路由表由后端维护好,通过接口前端拿到数据,然后使用 addRoutes方法添加到 router,最后根据路由表渲染菜单。

实现如下:
1、在 route.js 里面配置通用的路由(404,login 等)。

import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
const router = new Router({
    
    
  mode: 'hash',
  routes:[{
    
    
  		path:'/',
		redirect:'/login'
  },{
    
    
		path:'/login',
		name:'login',
		component: () => import('../view/login')
	},{
    
    
		path:'/404',
		name:'404',
		component: () => import('../view/404')
	}]
})
export default router;

2、接口获取动态路由信息(与后端同时约定好数据的格式),这个时候只需要返回该用户有权限的路由表即可。

{
    
    	
	code:200
	message:'查询成功'
	success:true
	data: {
    
    
	    router: [
	      {
    
    
	        path: "/",
	        component: "index",
	        name: "home",
	        meta: {
    
    
	          title: "Home"
	        },
	        children: [
	          {
    
    
	            path: "menu1",
	            name: "menu1",
	            component: "menu1",
	            meta: {
    
    
	              title: "菜单1",
	              icon: "el-icon-info"
	            }
	          }
	        ]
	      }]
	 }
}

3、这里 component 是一个字符串,需要转换成路径,然后将处理好的数据保存到 vuex 和 localStorage 里面。

 function filterRouter(routers) {
    
     // 遍历后台传来的路由字符串,转换为组件对象
    const accessedRouters = routers.filter(route => {
    
    
      if (route.component) {
    
    
          route.component = _import(route.component)
      }
      if (route.children && route.children.length) {
    
    
          route.children = filterRouter(route.children)
      }
      return true
    })
    return accessedRouters
  }

function _import (file) {
    
    
    return () => import('../views/' + file)
}

4、在 App.vue 文件的 created 生命周期使用 addRoutes方法将通过权限数据处理过的最新路由表加入到 router 里面去。

//处理好数据之后
this.$router.options.routes = routerList;
this.$router.addRoutes(routerList);

5、在菜单页面,使用 this.$router.options.routers 来获取最新路由对象,通过 v-for 循环渲染菜单栏。

建议:处理好的路由表存到 localStorage 里的时候最好加密处理,防止用户通过本地修改。

猜你喜欢

转载自blog.csdn.net/weixin_43299180/article/details/114276852