vue实现动态路由 权限控制菜单功能【转 整理】
先上效果图作为一个Java的后端开发 因为公司需求 也刚接触vue 自己慢慢摸索 终于有了一丝丝效果 作为一个小白 下面有什么说的不对的地方欢迎矫正修改vue项目实现动态路由的方式大体可分为两种:1、前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由)2、后台传来当前用户对应权限的路由表,前端通过调接口拿到后处理(后端处理路由)主要使用到的一些vue技术 vue-rou
先上效果图
作为一个Java的后端开发 因为公司需求 也刚接触vue 自己慢慢摸索 终于有了一丝丝效果 作为一个小白 下面有什么说的不对的地方欢迎矫正修改
vue项目实现动态路由的方式大体可分为两种:
1、前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由)
2、后台传来当前用户对应权限的路由表,前端通过调接口拿到后处理(后端处理路由)
主要使用到的一些vue技术 vue-router的beforeEach 和addroutes 还有前端element 在这里不使用vuex 后期有小伙伴需要的可以加入使用 建议先把这几个知识点学会 再来看看会好很多 不然很吃力
官网是最好的老师 附:
vue router 官网 vue-router
思路整理:
1、首先后台会返回一个json格式的路由表,因为这里不涉及,为力减轻压力,所以直接模拟一份路由直接使用(可以使用mock生成)
2、我们将路由分成两份 一份是公共的路由 例如/404 /login等 一份就是我们所使用的的动态路由 在创建实例的时候 我们先把公共路由加载进去
3、用户登录后会有不同的权限例如:管理员与普通用户,所以登录后我们把登录的用户名存到localStorage中
4、route通过beforeEach和addroutes对原有的路由表进行重新的过滤 最后获得权限的路由表
5、最后通过element对新的路由表进行渲染展示
下面上代码:
1、首先建立一个空的vue工程 我是用的是脚手架cli4
2、假如从后台那里得到的数据是这样的:
/src/router/index.js
export const permissionRouter = [
{
path: "/example",
component: layout,
name: "Example",
meta: {
title: "案例",
icon: "el-icon-success",
roles: ['admin', 'user']
},
children: [{
path: "/example/table",
name: "Table",
component: table,
meta: {
title: "table案例",
icon: "el-icon-goods",
roles: ['admin']
},
// 三级菜单写法,对应demotable案例下边的两个菜单
children: [{
path: "table1",
name: "Table1",
component: tableFirst,
meta: {
title: "table1",
icon: "el-icon-mobile-phone",
roles: ['admin']
}
},
{
path: "table2",
name: "Table2",
component: tableSecond,
meta: {
title: "table2",
icon: "el-icon-service",
roles: ['admin']
}
}
]
},
{
path: "tree",
name: "Tree",
component: tree,
meta: {
title: "树形菜单",
icon: "el-icon-upload",
roles: ['user', 'admin']
}
}
]
}
]
我们先把公共路由加载进去 动态路由按照思路直接创建
/src/router/index.js
export const fixedRouter = [{
path: '',
component: reload,
hidden: true
},
{
path: '',
component: layout, //整体页面的布局(包含左侧菜单跟主内容区域)
children: [{
path: 'main',
component: main,
meta: {
title: '首页', //菜单名称
roles: ['user', 'admin'], //当前菜单哪些角色可以看到
icon: 'el-icon-info' //菜单左侧的icon图标
}
}]
},
]
export default new Router({
routes: fixedRouter
})
2、先把我们登陆的信息用户权限保存到localStorage中
/src/components/reLoad.vue
<template>
<div class="load_wapper">
<el-form class="form_wapper" size="mini" :model="formModel">
<el-form-item label="用户名:">
<el-input v-model="formModel.user"></el-input>
</el-form-item>
<el-form-item label="密码:">
<el-input v-model="formModel.password"></el-input>
</el-form-item>
<el-form-item align="center">
<el-button @click="loadBtn" type="primary" plain> 登录</el-button>
</el-form-item>
<span>管理者:admin,密码:1</span>
<br />
<span>普通用户:user,密码:1</span>
</el-form>
</div>
</template>
<script>
export default {
components: {
},
data() {
return {
formModel: {
user: 'admin',
password: '1'
}
}
},
methods: {
loadBtn() {
// 这里应该调用接口,将用户信息传给后端,后端查到用户的角色,类似于:
// axios.post('/temp',this.formModel).then(res=>{})
// 我暂时就不模拟了,直接取
let getUserRole = this.formModel.user === 'admin' ? 'admin' : 'user'
localStorage.setItem('userRole', getUserRole)
// window.location.href="/main"
this.$router.push({
path: '/main'
})
}
},
mounted() {
}
}
</script>
3、使用vue-router 的导航守卫进行全局设置 在src文件夹下面创建一个js文件 这个文件需要直接导入到main.js 文件中
/src/permission.js (关键点是能够理解beforeEach函数里面的意思 如何进行匹配用户权限和筛选 再到整合公共路由)
// 取到需要权限判断的路由表
import { permissionRouter, fixedRouter } from '@/router'
import router from '@/router'
var addRouFlag = false
router.beforeEach((to, from, next) => {
// 取到用户的角色
let GetRole = localStorage.getItem("userRole")
// 如果登录了
if (GetRole&&GetRole !== 'unload') {
next() //next()方法后的代码也会执行
// 1.如果路由表 没根据角色进行筛选,就筛选一次
if (!addRouFlag) {
addRouFlag = true
// 2.根据用户的角色、和需要动态展示的路由,生成符合用户角色的路由
var getRoutes = baseRoleGetRouters(permissionRouter, GetRole.split(","))
// 3.利用global属性,让渲染菜单的组件sideMeuns.vue重新生成左侧菜单
global.antRouter = fixedRouter.concat(getRoutes) // 利用数组函数将静态路由和动态路由合并
// 4.将生成好的路由addRoutes
router.addRoutes(fixedRouter.concat(getRoutes))
// 5.push之后,会重新进入到beforeEach的钩子里,直接进入第一个if判断
router.push({ path: to.path })
}
} else {
// 用户没登录,跳转到登录页面
if (to.path === '/') {
next()
} else {
next('/')
}
}
})
function hasPermission(route, roles) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.indexOf(role) >= 0)
} else {
return true
}
}
// 根据用户的角色取到该用户对应的路由
function baseRoleGetRouters(allRoutes, roles) {
// allRoutes是动态路由表
// roles是取到的用户角色,数组
let rightRoutes = allRoutes.filter((route) => {
if (hasPermission(route, roles)) {
if (route.children && route.children.length) {
route.children = baseRoleGetRouters(route.children, roles)
}
return true
}
return false
})
return rightRoutes
}
4、最后将得到过滤的新路由表进行v-for展示
/src/components/sideMeuns.vue
<template>
<div class="">
<!-- 遍历路由表,生成左侧菜单 -->
<template v-for="item in meuns" >
<div v-if="!item.hidden" v-bind:key="item.id">
<!-- 一级菜单的情况 -->
<template v-if="item.children&&item.children.length===1">
<router-link :to="item.path+'/'+item.children[0].path">
<!-- index跟浏览器地址对应,这样菜单才能显示选中状态 -->
<el-menu-item :index="item.path+'/'+item.children[0].path">
<template slot="title">
<!-- 设置icon -->
<i v-if="item.children[0].meta.icon" :class="item.children[0].meta.icon"></i>
<!-- 菜单名称 -->
{{item.children[0].meta.title}}
</template>
</el-menu-item>
</router-link>
</template>
<!-- 一级菜单的情况 end-->
<!-- 多级菜单 -->
<template v-else>
<el-submenu :index="item.path">
<template slot="title">
<i :class="item.meta.icon"></i>
{{item.meta.title}}
</template>
<!-- 遍历子菜单 -->
<template v-for="itemChild in item.children" >
<div v-if="!itemChild.hidden" v-bind:key="itemChild.id">
<!-- 当发现存在3级或大于3级菜单时,重新遍历当前组件 -->
<template v-if="itemChild.children&&itemChild.children.length>0">
<side-meuns :routes="[itemChild]" class="nest-menu"></side-meuns>
</template>
<!-- 2级菜单时-->
<template v-else>
<router-link :to="item.path+'/'+itemChild.path">
<el-menu-item :index="item.path+'/'+itemChild.path">
<i v-if="itemChild.meta.icon" :class="itemChild.meta.icon"></i>
{{itemChild.meta.title}}</el-menu-item>
</router-link>
</template>
</div>
</template>
<!-- 遍历子菜单 end-->
</el-submenu>
</template>
<!-- 多级菜单 end-->
</div>
</template>
</div>
</template>
<script>
import '@/styles/index.css'
export default {
name: 'sideMeuns',
props: {
routes: {
type: Array,
default: () => []
}
},
data() {
return {
meuns: ''
}
},
mounted() {
this.meuns = this.routes
}
}
</script>
5、这样就完成了动态路由的设置 中间还有一部分缺少的视图 是用于跳转展示使用的 自己随意设置就可以 我的视图:
--------最后附上我的Gitee地址 不理解的小伙伴可以对照着去理解 希望对你有帮助-------
点击获取源码
更多推荐
所有评论(0)