前言

在做Vue管理系统的时候,都会遇到的一个需求:每个用户的权限是不一样的,那么他可以访问的页面(路由),可以操作的菜单选项是不一样的,如果由后端控制,我们前端需要去实现动态路由,动态渲染侧边菜单栏。

动态路由

  • 在本示例管理系统中,由于每个用户的权限不一样,拥有的可以访问的路由页面也不一样,用户能访问的路由页面都是后端根据权限动态配置的
  • 我们前端需要根据后端接口返回的路由表去动态增删路由,从而生成这个用户所拥有的路由。

重点:实现动态路由api

  • router.addRoute() //应用程序已经运行的时候添加路由
  • router.removeRoute() // 应用程序已经运行的时候删除路由

定义共用的页面路由(无论哪个用户都会有的)

如无论什么用户都可访问登录页login,错误页面404。

接口数据:这里模拟接口的路由数据(这里进行数据精简,便于演示,实际情况可能要进行数据结构格式的转换)

添加动态路由进去的时机(router.beforeEach)

利用全局前置守卫router.beforeEach,在跳转路由前先判断是否已经添加过动态路由了,如果没有,则先获取数据进行添加路由。(router.beforeEach也会做登录等拦截,这里省略)

利用router.getRoutes()方法查看现有路由,我们将会看到根据新的路由添加进去了。

这样我们就实现了动态路由啦!

  • 这是我们要实现的效果,根据接口数据动态渲染,不论层级多少都可以自动渲染,一级菜单,二级菜单,三级甚至更多(不过一般最多只到三级哈哈)。

很多组件库都可以实现这个功能,这里我们将使用 Ant Design of Vue 组件库的内嵌菜单组件(如下图)去实现,有父菜单,子菜单,父级菜单的是用 a-sub-menu 包裹,子菜单的是直接使用 a-menu-item,大家可以去看文档看一下组件的使用。

接口数据:这里模拟接口的菜单数据(实际情况可能要进行数据结构格式的转换)

重点:组件递归

使用v-for循环菜单数据数组,渲染组件库 ant design of vue的菜单组件,这时分两种情况,

  • 如果有children,那么渲染a-sub-menu(父级菜单),并包裹自身组件,把children数据传递给调用的自身组件,也就是递归调用组件自身,那么调用的自身组件就会重复上面逻辑的判断,直到没有children,也就是遇到了第二种情况,结束递归调用。
  • 如果没有children,那么直接显示 a-menu-item (子菜单)

下面为菜单组件,组件名为MenuList,递归调用的时候要用到组件名,以达到根据不同数据渲染菜单的情况

没有图标版本

效果如下

有图标版本

图标是根据接口数据的icon去匹配的,有多种方法,例如使用iconFont、svg、png,主要是去对应图标的名字,这里使用组件库提供的使用icon的iconFont方法。

效果如下:

这样我们就实现了动态侧边菜单栏啦!

代码:

//1.定义共用的页面路由(无论哪个用户都会有的)
import { createRouter, createWebHashHistory } from 'vue-router'const publicRoutes = [{path: '/',redirect: { path: '/login' }},{path: '/login',name: 'login',component: () => import('../views/login')},{path: '/404',name: '404',component: () => import('../views/404')},{path: '/home',name: 'home',component: () => import('../views/home'),redirect: '/welcome',children: [{path: '/:pathMatch(.*)*',    // 捕获所有路由或 404 Not found 路由component: () => import('../views/welcome')}]}
]const router = createRouter({history: createWebHashHistory(),routes: publicRoutes
})export default router//2.模拟接口的路由数据
navigationList : [{id: 1,icon: 'icon-jurassic_user',name: '用户管理',url: '/user'},{id: 2,icon: 'icon-jurassic_user',name: '角色管理',url: '/role'},{id: 3,icon: 'icon-shebei',name: '设备管理',url: '/device'}
]//3.添加动态路由进去的时机(router.beforeEach)
import store from '@/store'
//这里我用vuex的一个变量 asyncRoutestMark 来标识是否拼接过路由
router.beforeEach((to, from, next) => {if (!store.state.asyncRoutestMark) {// navigationList 是上面模拟接口返回的数据// 这里将新的路由都作为 home 的子路由(实际开发根据情况)// meta 是存储一些信息,可以用于权限校验或其他navigationList.forEach( navigation => {router.addRoute('home', {path: navigation.url,meta: { name: navigation.name, isAsync: true, icon: navigation.icon },name: navigation.url,component: () => import(`../views/${navigation.url}`)})})console.log(router.getRoutes(), '查看现有路由')store.commit('setAsyncRoutestMark', true) // 添加路由后更改标识为truenext({ ...to, replace: true })     //路由进行重定向放行} else {next()}
})//4.模拟接口的菜单数据
menuList :[{url: '',name: '人员管理',icon: 'icon-renyuan',menuId: 1,children: [{url: '/user',name: '用户管理',icon: 'icon-jurassic_user',menuId: 1001,children: []},{url: '/role',name: '角色管理',icon: 'icon-jiaose',menuId: 1002,children: []}]},{url: '/device',name: '设备管理',icon: 'icon-shebei',menuId: 2}
]//5.无图标
<template><template v-for="menu in menuList" :key="menu.menuId"><a-sub-menu v-if="menu.children && menu.children.length" :key="menu.menuId"><template #title>{{ menu.name }}</template><MenuList :menuList="menu.children" /></a-sub-menu><a-menu-item :key="menu.menuId" v-else><span>{{ menu.name }}</span></a-menu-item></template>
</template>
<script setup>
import { defineProps } from 'vue'
defineProps({menuList: {type: Array,default: () => []}
})
</script>//6.有图标
<template><template v-for="menu in menuList" :key="menu.menuId"><a-sub-menu v-if="menu.children && menu.children.length" :key="menu.menuId"><template #icon><icon-font :type="menu.icon" /></template><template #title>{{ menu.name }}</template><MenuList :menuList="menu.children" /></a-sub-menu><a-menu-item :key="menu.menuId" v-else><template #icon><icon-font :type="menu.icon" /></template><span>{{ menu.name }}</span></a-menu-item></template>
</template>
<script setup>
import { defineProps } from 'vue'
import { createFromIconfontCN } from '@ant-design/icons-vue'
const IconFont = createFromIconfontCN({scriptUrl: '//at.alicdn.com/t/font_2572336_4hg62uu7hxd.js'
})
defineProps({menuList: {type: Array,default: () => []}
})
</script>

如何利用Vue3管理系统实现动态路由和动态侧边菜单栏相关推荐

  1. uniapp 移动端上传文件_基于 uniapp 实现动态路由和动态 Tabbar

    本文转载自 字节逆旅 公众号,感谢作者的好文分享✌️,点击阅读原文可以查看作者的掘金链接. uniapp用来开发app还是比较方便快捷的,官网教程[1]挺细致,几乎所有问题都能找到答案.网上也有不少入 ...

  2. 动态路由和动态路由中的RIP协议

    动态路由和动态路由中的RIP协议 一.动态路由 1.动态路由的特点 2.选择依据:度量值 3.收敛 4.静态路由与动态路由的比较 二.动态路由协议分类 三.RIP是距离矢量路由选择协议 1.RIP的基 ...

  3. Zuul动态路由及动态Filter实现

    一, Zuul动态路由实现 动态路由需要达到可持久化配置,动态刷新的效果.不仅要能满足从spring的配置文件properties加载路由信息,还需要从Redis加载我们的配置.另外一点是,路由信息在 ...

  4. zuul 动态路由mysql_zuul 动态路由 - typistw的个人空间 - OSCHINA - 中文开源技术交流社区...

    前言 在微服务架构体系下,随着时间的推移,难免会碰到由于前期服务粒度的划分不能完全满足后续需求的增长,造成"微"服务的二度拆分.拆分不可避免的会导致服务在整个系统中的链路发生变化, ...

  5. ribbon 配置 动态更新_Netflix开源工具:在SpringBoot实现动态路由

    前言 假设你有一个服务A,要调用服务B(有三个实例,B1.B2.B3),如何只调用其中的B1和B2,屏蔽掉B3?实际上解决方法大致分为两类. 一种是外部路由,就是通过网关等组件,在请求链路上进行路由选 ...

  6. SpringCloud微服务Zuul网关动态路由

    SpringCloud微服务Zuul网关动态路由 zuul动态路由 1. 网关层动态配置路由映射规则 2. 将同一个请求根据自定义的规则,路由到不同服务中 FeignClient动态请求 实现功能 实 ...

  7. 快速搭建一个网关服务,动态路由、鉴权看完就会(含流程图)

    [文章来源]https://sourl.cn/tcbSPi 前 言 本文记录一下我是如何使用Gateway搭建网关服务及实现动态路由的,帮助大家学习如何快速搭建一个网关服务,了解路由相关配置,鉴权的流 ...

  8. 【计算机网络】网络层 : 路由算法 ( 路由算法分类 | 静态路由算法 | 动态路由算法 | 全局性动态路由算法 | 分散性动态路由算法 | 分层次路由选择协议 )

    文章目录 一.路由算法 二.路由算法 分类 三.静态路由算法 四.动态路由算法 五.动态路由算法 分类 六.分层次的路由选择协议 一.路由算法 路由算法 : 选择数传输的 "最佳路由&quo ...

  9. 4.2.1 路由算法与路由协议概述(静态路由和动态路由---距离-向量路由算法---链路状态路由算法、层次路由)

    文章目录 0.思维导图 1.路由算法分类与路由表 2.静态路由和动态路由 3.动态路由的两种算法:链路状态路由算法和距离向量路由算法 4.层次路由 0.思维导图 1.路由算法分类与路由表 路由器转发分 ...

最新文章

  1. nyoj——297(期望)
  2. 3.4.1 流量控制与可靠传输机制
  3. 【AutoML】连续可微分架构如何用于网络结构搜索
  4. 创建自定义Widgets小部件扩展
  5. 抽象类与接口 day-11.2
  6. sklearn自学指南(part32)--保序回归
  7. 项目管理指标_项目经理必掌握的九大项目管理问题
  8. 基于结构体的二进制文件读写
  9. VC6 Win7 x64 提示 Remote Executable path And File Name
  10. 自动改变文字大小和颜色的javascript效果
  11. java memcached设置过期时间_Memcached的MemCachedClient设置过期时限
  12. springcloud官方文档_springcloud-microservice 快速构建分布式系统
  13. linux双系统安装nvidia,ubuntu 16.04(Windows 10双系统+grub引导)无法进入tt1~tt6(NVIDIA驱动安装相关-黑屏,login loop,分辨率)...
  14. 光学定位与追踪技术_贺岁片《疯狂外星人》中徐峥出演外星人?幕后动捕技术了解一下...
  15. 关于微信公众号的迁移,在此记录一下
  16. 问答社区竞品分析——知乎与悟空的较量
  17. 发布园友设计的新款博客皮肤BlueSky
  18. 【doris】V1.2.2安装部署单机版or集群版
  19. 实验五——数据库设计实验
  20. 虚拟服务器vps怎么扩展,vps虚拟服务器怎么用

热门文章

  1. 三种求平方根的算法——C/C++
  2. luckysheet 只读模式和编辑模式
  3. 计算机win是什么键,Windows键是哪个 电脑上的Win键在哪?【图文】
  4. Android 点九图机制讲解及在聊天气泡中的应用
  5. String Utils 工具类介绍大全 isAnyEmpty isAnyBlank stripToNull 等,一篇文章找全所有答案!
  6. java pdf替换内容_Java添加、提取、替换和删除PDF图片
  7. java代码:双色球号随机生成(极其简洁!)
  8. 导出带有表格的word文件时,换页自带表头,避免复杂的表格数行数计算
  9. 从零开始成为优秀的交互设计师
  10. 两个同品牌路由器有线连接