vue后台管理系统之权限管理
权限管理概念
还是老规矩先捋概念,权限管理分哪几块?首先用户是分角色的,然后每个角色有不同权限,这是由你的账号性质决定的,然后分为菜单权限,路由的权限,按钮的权限,接口的权限。今天我们主要聊一聊比较核心菜单和路由的权限。
菜单的权限
菜单权限的代码主要在vuex中,下面给大家看vuex里面的代码,在store/index.js中
state: {
leftList: JSON.parse(localStorage.getItem('leftList')),//左边菜单栏结构树的数据从本地获取,因为每次刷新,vuex的数据会丢失,每次默认从本地拿,就会防止刷新后数据会丢失。
},
mutations:{
setLeftList (state, data) {//这个方法就是通过接口拿到结构树的数据再调用的,主要用于存数据。
state.leftList = data; //赋值操作
localStorage.setItem('leftList', JSON.stringify(data))//然后本地也存一份,这样上面的state每次刷新,才在本地有数据拿
},
侧边菜单栏的数据就是拿vuex中的数据直接循环渲染生成的,我就不多说了,但是菜单渲染出来后,这只是菜单的权限,我们页面权限怎么做呢?接下来我们看看路由权限的代码。
路由的权限
首先一个问题,路由的权限怎么来?因为我们只拿到了结构树的数据,并没有路由权限的数据啊,所以我们前端要自己来定义,根据结构树的数据,来决定我们有哪些路由页面是可以显示的,没有的话就会跳404页面。从而来达到一个权限的效果。接下来我们看路由处理的代码。在router/index.js中
let routes = [ //定义路由的数组
{ //首先是一个重定向路由到首页
path: '/',
redirect: to => {
return {
name: 'Home'
}
},
},
{ //home页是一级路由,主要是放侧边栏,导航栏和二级路由视口的
path: '/home',
name: 'Home',
component: Home,
redirect: to => {
return {
name: 'Demo'
}
},
children: [ //所有的路由页面都要添加到这个children里来
{
path: '/demo', //demo是二级路由默认展示的空白页面
name: 'Demo',
component: Demo,
meta: {
title: '默认展示页'
}
}
]
}
]
//首先是routes中必须有的页面,我放了一个home页,和一个默认展示页
//但是一开始不要放404页面,因为添加路由页面是异步,动态添加路由后,每次刷新会默认跳404页面,怎么解决后面说。
//然后在下面把所有需要另外添加的路由页面,都单独写成一个对象的形式。
//这里我只写一个,你有多少要异步添加的页面就写多少个,我主要是让你看结构
//组件引入必须用懒加载的形式,这点很重要
const poliedrule = { //
path: '/policylistedit',
name: 'Policylistedit',
component:() => import('views/policymanage/policylistedit.vue'),
meta: {
title:'页面名字'
}
}
const ruleMapping = { //然后做一个枚举,做一个映射关系,后面方便循环
'policylistedit':poliedrule //键名就是你结构树中每个菜单的url名称,键值就是上面对应的每一个路由对象
}
//然后再继续在下面定义一个异步添加路由权限页面的函数并抛出,因为别处要用的
export function initDynamicRoutes() {
const currentRoutes = router.options.routes; //获取当前路由规则
const lefttList = store.state.leftList;//获取之前存在vuex中结构树的数据
lefttList.forEach(item => { //循环
item.Children.forEach(it => {//因为结构树分上级菜单和真正跳转路由的菜单,上级菜单是没有url,只有最里层才有,所以我们要循环每一项看他的children的有没有子集
if (it.Children.length == 0) { //没有子元素就是路由菜单,可以跳转路由的那种,带url的
const temp = ruleMapping[it.url] //这一步其实就是取出所有子菜单对应的路由对象
currentRoutes[1].children.push(temp)//然后做push操作
} else {
it.Children.forEach(el => { //否则有子元素就是顶级菜单,继续循环。因为本项目最多三层,所以我直接循环,层级比较多的建议用递归方法
const tem = ruleMapping[el.url] // 和上面一样的操作
currentRoutes[1].children.push(tem)
})
}
})
});
router.matcher = new VueRouter().matcher //这一步主要是去重,防止有重复的路由对象,这一步很关键
router.addRoutes(currentRoutes)//上面我们只是添加的路由规则,并没有真正的加到router里,所以我们需要用到这个独特的api,但是这个方法vue3.0用不了,需谨慎哈。
router.addRoutes([{
path: '*',
name: '404',
component: () => import('views/notundefund/404.vue'),,
}])
}
//因为addroutes添加路由是异步的,path为*号就是匹配不到就会跳这个页面
//所以要最后加这个路由,否则每次刷新浏览器路由页面还在加载就先跳404页面了,对用户很不友好,所以我们需要最后加载
const router = new VueRouter({ //然后挂载到router实例上
routes
});
export default router
最后在合适的地方使用这些方法
// 在app.vue中使用,并附上代码
import { getTree} from "network/api"; //引入获取结构树的接口方法
import { initDynamicRoutes } from "./router/index" //导入上面route.js中的那个添加路由页面的方法
export default {
methods: {
gettree() {
getTree().then((res) => { //调用获取结构树的方法
if(res.code == 1){ //成功状态
this.$store.commit('setLeftList',res.data.rows); //通过vuex中的方法存数据
initDynamicRoutes() //最后异步添加有权限的路由
}
});
},
},
created() {
this.gettree(); //进入项目就调用,每次浏览器刷新也会再次调用,这样就不会丢失数据
},
以上就是权限管理所有代码,如果问题和指教,欢迎评论留言,鄙人乐意交流,相互学习。