在我们开发后台管理系统的过程中,会有不同的人来操作系统,包括admin(管理员)、superAdmin(超级管理员),以及各种运营和财务人员。为了区分这些人,会给不同的人分配不同的角色来显示不同的菜单,这必须通过动态路由来实现。下面介绍vue实现动态路由。有需要的朋友可以参考一下。
: 目录
1.前端控制1。在router.js文件中(分别在router.js中写静态路由和动态路由)
2.store/permission.js(在vuex中维护一个状态,通过分配角色控制菜单是否显示)
3.src/permission.js4,侧边栏可以从vuex获取数据进行渲染。2.后端控制路由。1.store/permission.js,发送请求获取vuex中的数据。2.组织一个数据结构并存储在表中。3.写一个转换方法,把采集到的数据转换成路由器结构
主流的实现方式:
。下面简单说一下两种方法的优势。毕竟如果你以前没做过,说再多也看不懂,还是要看代码的。
前端控制
没有后端帮助,路由表在前端维护。
逻辑比较简单,容易上手。
后端控制
这样更安全。
路由表保存在数据库中。
一、前端控制
思路:在路由配置中,通过meta属性扩展权限相关的字段,通过判断路由卫士中的这个权限标志,实现路由的动态增加和页面跳转;例如,我们添加一个角色字段来控制角色。
具体方案:
1.根据登录用户的账号返回前端用户的角色。
2.前端根据用户的角色匹配路由表的meta.role。
3.匹配的路由形成可访问的路由。
核心代码逻辑
1.在router.js文件中(分别在router.js中写静态路由和动态路由)
从“vue”导入Vue
从“vue路由器”导入路由器
Vue.use(路由器)
从“@/layout”导入布局
//constantRoutes静态路由,主要是登陆页,404页等。不需要动态路由。
出口常量constantRoutes=[
{
路径:“/redirect”,
组件:布局,
隐藏:真实,
儿童:[
{
路径:“/redirect/:path*”,
component:()=import( @/views/redirect/index )
}
]
},
{
路径:“/login”,
组件:()=import(@/views/login/index ),
隐藏:真
},
{
路径:“/404”,
component:()=import( @/views/error-page/404 ),
隐藏:真
},
{
路径:“/401”,
component:()=import( @/views/error-page/401 ),
隐藏:真
}
]
//异步路由动态路由
导出常量异步路由=[
{
路径:“/权限”,
组件:布局,
重定向:“/权限/页面”,
alwaysShow:真的,
名称:权限,
元:{
标题:“许可”,
图标:“锁定”,
//核心代码可以被分配的角色遍历,所以是否显示。
//这意味着管理员和编辑的角色。可以显示该菜单。
角色:[管理员,编辑]
},
儿童:[
{
路径:“页面”,
组件:()=import( @/views/permission/page ),
名称:页面权限,
元:{
标题:“页面权限”,
//这意味着只有admin可以显示
角色:[admin]
}
}
]
}
]
const createRouter=()=新路由器({
scrollBehavior: ()=({ y: 0 }),
路线:constantRoutes
})
const router=createRouter()
//这个是用来重置路由的,很有用。别看这几行代码。
导出函数resetRouter() {
const newRouter=createRouter()
router . matcher=new router . matcher
}
导出默认路由器
2.store/permission.js(在vuex中维护一个状态,通过分配角色控制菜单是否显示)
从“@/router”导入{ asyncRoutes,constantRoutes }
//此方法用于将角色与route.meta.role进行匹配
函数具有权限(角色,路由){
if(route . meta route . meta . roles){
返回roles . some(role=route . meta . roles . includes(role))
}否则{
返回true
}
}
//这个方法是通过递归来遍历路由,把有权限的路由给遍历出来
导出函数filterAsyncRoutes(路由,角色){
const res=[]
routes.forEach(route={
const tmp={.路线}
if (hasPermission(roles,tmp)) {
if (tmp.children) {
tmp。children=filterasyncproutes(tmp。孩子、角色)
}
资源推送(tmp)
}
})
返回资源
}
常量状态={
路线:[],
添加路由:[]
}
常量突变={
设置路线:(州,路线)={
//这个地方维护了两个状态一个是添加路由器,一个是路线
state.addRoutes=routes
状态。路线=固定路线。串联(路线)
}
}
常量操作={
generateRoutes({ commit },roles) {
返回新承诺(resolve={
让访问路由
如果(角色。包括(管理){
accessedRoutes=asyncRoutes || []
}否则{
//核心代码,把路由和获取到的角色(后台获取的)传进去进行匹配
访问的路由=filterasyncproutes(异步路由,角色)
}
//把匹配完有权限的路由给设置到vuex里面
提交(设置路由,访问路由)
解析(访问路由)
})
}
}
导出默认值{
命名空间:对,
状态,
突变,
行动
}
3、src/permission.js(新建一个路由守卫函数,可以在main.js,也可以抽离出来一个文件)
这里面的代码主要是控制路由跳转之前,先查一下有哪些可访问的路由,登录以后跳转的逻辑可以在这个地方写
//permission.js
router.beforeEach(收件人,发件人,下一个)={
if (store.getters.token) { //判断是否有代币
if (to.path===/login) {
next({ path:/ });
}否则{
//判断当前用户是否已拉取完用户信息信息
如果(存储。吸气剂。角色。长度===0){
store.dispatch(GetInfo ).然后(res={ //拉取信息
常量角色=资源数据。角色;
//把获取到的作用传进去进行匹配,生成可以访问的路由
store.dispatch(GenerateRoutes ,{ roles }).然后(()={
//动态添加可访问路由表(核心代码,没有它啥也干不了)
路由器。添加路线(商店。吸气剂。添加路由器)
//黑客方法确保添加路线已完成
下一个({.到,替换:true })
})
}).接住(错误={
控制台。日志(错误);
});
}否则{
next() //当有用户权限的时候,说明所有可访问路由已生成如访问没权限的全面会自动进入404页面
}
}
}否则{
if (whiteList.indexOf(to.path)!==-1) { //在免登录白名单,直接进入
next();
}否则{
下一步(/log in );//否则全部重定向到登录页
}
}
})
4、侧边栏的可以从vuex里面取数据来进行渲染核心代码是从路由器取可以用的路由对象,来进行侧边栏的渲染,不管是前端动态加载还是后端动态加载路由,这个代码都是一样的
!-布局/组件/侧边栏。vue -
埃尔菜单
:default-active=activeMenu
:collapse=isCollapse
:background-color=变量。menubg
:text-color=variables.menuText
:unique-opened=false
:active-text-color=变量。菜单活动文本
:collapse-transition=false
模式=垂直
//把取到的路由进行循环作为参数传给子组件
侧栏-项目v-for= routes中的 route :key= route。“path”:item=“route”:base-path=“route。路径/
/el-menu
//获取有权限的路由
路线(){
归还这个.路由器.选项.路由
}
!-布局/组件/siderbarItem.vue -
模板槽=标题
item v-if= item。 meta :icon= item。元项目。meta。 icon :title= item。meta。标题/
/模板
侧栏项目
v-for= item。儿童中的子级
:key=child.path
:is-nest=true
:item=child
:base-path=解析路径(子级。路径)
嵌套菜单
/
道具:{
//路由对象
项目:{
类型:对象,
必填:真
},
isNest: {
类型:布尔型,
默认值:错误
},
基本路径:{
类型:字符串,
默认值:""
}
}
前端控制路由,逻辑比较简单。后端只需要存储用户的角色,前端匹配用户的角色。但是如果增加新的角色,那就很痛苦了,每个都要加。
二、后端控制路由
后端控制大致思路是:
路由配置放在数据库表中。用户登录成功后,根据角色权限,将授权菜单发送到前端,格式化为页面路由标识的结构,再渲染到页面菜单;用户登录后,后端根据用户的角色直接生成可访问的路由数据。注意这个地方是数据。
根据前端返回的路由数据,转换成自己需要的路由结构。
具体逻辑:
Router.js只放一些静态路由,比如login和404。
组织一个数据结构并存储在表中。
从后端获取路由数据,写一个数据转换的方法,说说数据转换成可访问的路由。
它还维护vuex状态,并将转换后的路由存储到vuex中。
侧栏还从路线中提取数据进行渲染。
因为前端控制和后端控制,后端的流程大多是一样的,所以这个地方只看前面不同的流程:
1、store/permission.js,在vuex里面发送请求获取数据GenerateRoutes({ commit },data) {
返回新承诺((解决,拒绝)={
getRoute(数据)。然后(res={
//转换采集到的数据,然后存储在vuex中。
const accessedRouters=arrayToMenu(RES . data)
accessed routers . concat([{ path: * ,redirect: /404 ,hidden: true }])
提交(设置路由器,访问路由器)
解决()
}).catch(错误={
拒绝(错误)
})
})
}
2、整理一份数据结构,存到表里//页面路由格式
{
路径:“/form”,
组件:布局,
儿童:[
{
路径:“索引”,
名称:表单,
组件:()=import(@/views/form/index ),
meta: {标题:表单,图标:表单 }
}
]
}
//排序后的数据格式
//一级菜单
//0的parentId可以作为一级菜单。id最好选择4位数。至于为什么开发项目就知道了。
{
编号:1300
parentId: 0
标题:“菜单管理”
路径:“/menu”
隐藏:假
组件:空
隐藏:假
名称:“菜单”
},
//二级菜单
//如果Parentid不为0,可以将parentId与一级菜单的Id进行匹配,并推送给子级。
{
编号:1307
parentId: 1300
标题:“子菜单”
隐藏:假
路径:“菜单项”
Component: menu/menuItem //匹配本地文件地址。
隐藏:假
名称:“菜单项”
}
3、写一个转化方法,把获取到的数据转换成router结构导出函数arrayToMenu(array) {
常量节点=[]
//获取顶级节点
for(设I=0;I数组.长度;i ) {
const row=数组[i]
//这个exists方法是确定是否有子级。
如果(!exists(array,row.parentId)) {
nodes.push({
Path: row.path,//路由地址
Hidden: row.hidden,//All true,如果后端不匹配。
Component: Layout,//一般是和你的文件匹配的组件。
Name: row.name,//路由名称
Meta: {title: row.title,icon: row.name},//title是显示的名称。
Id: row.id,//路由的Id
重定向:“noredirect”
})
}
}
const toDo=Array.from(节点)
while (toDo.length) {
const node=toDo.shift()
//获取子节点
for(设I=0;I数组.长度;i ) {
const row=数组[i]
//推送到哪个父id等于哪个父id。
if (row.parentId===node.id) {
const child={
path: row.path,
名称:row.name,
hidden: row.hidden,
//核心代码,因为二级路由的组件需要匹配页面。
组件:require( @/views/ row . component /index . vue ),
meta: { title: row.title,icon: row.name },
id: row.id
}
if (node.children) {
node.children.push(子节点)
}否则{
node.children=[child]
}
toDo.push(子代)
}
}
}
返回节点
}
//看看有没有孩子
函数存在(rows,parentId) {
for(设I=0;I行.长度;i ) {
if (rows[i].id===parentId)返回true
}
返回false
}
这就是关于vue实现动态路由的详细文章。有关vue实现动态路由的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望大家以后能多多支持我们!