网站首页 > 技术文章 正文
在做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,在跳转路由前先判断是否已经添加过动态路由了,如果没有,则先获取数据进行添加路由。
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()方法查看现有路由,我们将会看到根据新的路由添加进去了。
动态侧边菜单栏
很多组件库都可以实现这个功能,这里我们将使用 Ant Design of Vue 组件库的内嵌菜单组件(如下图)去实现,有父菜单,子菜单,父级菜单的使用 a-sub-menu 包裹,子菜单的直接使用 a-menu-item,大家可以去看文档看一下组件的使用。
接口数据:
这里模拟接口的菜单数据(实际情况可能要进行数据结构格式的转换)
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>
效果如下
有图标版本
图标是根据接口数据的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>
效果如下:
猜你喜欢
- 2024-09-30 Vue Router 4 路由地址详解 vue router路由配置
- 2024-09-30 「vue基础」一篇浅显易懂的 Vue 路由使用指南( Vue Router 下)
- 2024-09-30 Vue Router 4 路由操作 - 路由导航
- 2024-09-30 为什么用vue.js,为什么前端开发46%的人都在用?
- 2024-09-30 vue-router 基础:4类路由跳转示例
- 2024-09-30 Vue Router 4 动态添加路由详解 vue router动态路由配置
- 2024-09-30 Vue进阶篇-Vue Router官方路由管理器
- 2024-09-30 循序渐进Vue+Element前端应用开发(3)—动态菜单和路由的关联处理
- 2024-09-30 哈希方式实现前端路由,核心是监听哈希事件hashchange
- 2024-09-30 前端开发框架VUE之路由vue-router
你 发表评论:
欢迎- 05-10如何优化数据库和前端之间的交互?
- 05-10前端代码优化小秘籍(前端优化24条建议)
- 05-10VS Code当中的15个神仙插件,值得收藏
- 05-10如何自己开发一个Google浏览器插件?
- 05-10前端流行框架Vue3教程:14. 组件传递Props效验
- 05-10吃了一年的SU,最好用的插件都在这了
- 05-10前端必看!这款神器让网站界面告别千篇一律
- 05-10程序员请收好:10个非常有用的 Visual Studio Code 插件
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端md5加密 (49)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- 前端懒加载 (45)
- 前端接口 (46)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle查询数据库 (45)
- oracle约束 (46)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)