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

作者:倾颜 时间:2024-05-05 09:25:34 

前言

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

动态路由

  • 在本示例管理系统中,由于每个用户的权限不一样,拥有的可以访问的路由页面也不一样,用户能访问的路由页面都是后端根据权限动态配置的

  • 我们前端需要根据后端接口返回的路由表去动态增删路由,从而生成这个用户所拥有的路由。

重点:实现动态路由api

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

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

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

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

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

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

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'
     }
]

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

利用全局前置守卫router.beforeEach,在跳转路由前先判断是否已经添加过动态路由了,如果没有,则先获取数据进行添加路由。(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: menu.url,
           component: () => import(`../views/${menu.url}`)
         })
       })
       console.log(router.getRoutes(), '查看现有路由')
       store.commit('setAsyncRoutestMark', true) // 添加路由后更改标识为true
       next({ ...to, replace: true })     //路由进行重定向放行
   } else {
     next()
   }
})

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

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

动态侧边菜单栏

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

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

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

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

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

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
 }
]

重点:组件递归

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

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

  • 如果没有children,那么直接显示 a-menu-item (子菜单)

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

没有图标版本

<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>

效果如下

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

有图标版本

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

<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管理系统实现动态路由和动态侧边菜单栏

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

来源:https://juejin.cn/post/7064857526776365070

标签:vue3,动态,路由
0
投稿

猜你喜欢

  • Python3对称加密算法AES、DES3实例详解

    2022-08-16 19:52:56
  • js显示动态时间的方法详解

    2024-05-05 09:12:35
  • 详解pandas中iloc, loc和ix的区别和联系

    2023-03-20 18:56:01
  • 这些有问题的细节设计

    2009-04-20 12:47:00
  • 分页技术原理与实现之分页的意义及方法(一)

    2024-01-26 14:29:16
  • PHP开发中常见的安全问题详解和解决方法(如Sql注入、CSRF、Xss、CC等)

    2023-10-02 23:03:06
  • Python实现网络自动化eNSP

    2021-01-18 00:48:04
  • Django如何创作一个简单的最小程序

    2022-09-04 04:57:28
  • Python爬虫之爬取最新更新的小说网站

    2022-04-01 17:11:07
  • python2 对excel表格操作完整示例

    2022-08-27 00:35:06
  • MSSQL2005数据附加失败报错3456解决办法

    2012-11-30 19:56:59
  • 给Python初学者的一些编程技巧

    2023-05-27 21:41:30
  • Python OpenCV招商银行信用卡卡号识别的方法

    2022-01-16 06:31:30
  • SQL Server数据库的三种创建方法汇总

    2024-01-19 01:20:24
  • 10个提高网站可用性的实用技巧[译]

    2009-06-12 12:37:00
  • PyQt5 QThread倒计时功能的实现代码

    2021-08-02 06:00:28
  • python 剪切移动文件的实现代码

    2023-06-10 05:21:14
  • Python闭包执行时值的传递方式实例分析

    2021-09-22 14:43:50
  • SQL查询效率:100w数据查询只需要1秒钟

    2008-12-09 14:36:00
  • Python自动生成代码 使用tkinter图形化操作并生成代码框架

    2021-04-26 08:47:30
  • asp之家 网络编程 m.aspxhome.com