如何利用Vue3管理系統(tǒng)實現(xiàn)動態(tài)路由和動態(tài)側(cè)邊菜單欄
前言
在做Vue管理系統(tǒng)的時候,都會遇到的一個需求:每個用戶的權限是不一樣的,那么他可以訪問的頁面(路由),可以操作的菜單選項是不一樣的,如果由后端控制,我們前端需要去實現(xiàn)動態(tài)路由,動態(tài)渲染側(cè)邊菜單欄。
動態(tài)路由
- 在本示例管理系統(tǒng)中,由于每個用戶的權限不一樣,擁有的可以訪問的路由頁面也不一樣,用戶能訪問的路由頁面都是后端根據(jù)權限動態(tài)配置的
- 我們前端需要根據(jù)后端接口返回的路由表去動態(tài)增刪路由,從而生成這個用戶所擁有的路由。
重點:實現(xiàn)動態(tài)路由api
- router.addRoute() //應用程序已經(jīng)運行的時候添加路由
- router.removeRoute() // 應用程序已經(jīng)運行的時候刪除路由
定義共用的頁面路由(無論哪個用戶都會有的)
如無論什么用戶都可訪問登錄頁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接口數(shù)據(jù):這里模擬接口的路由數(shù)據(jù)(這里進行數(shù)據(jù)精簡,便于演示,實際情況可能要進行數(shù)據(jù)結構格式的轉(zhuǎn)換)
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'
}
]添加動態(tài)路由進去的時機(router.beforeEach)
利用全局前置守衛(wèi)router.beforeEach,在跳轉(zhuǎn)路由前先判斷是否已經(jīng)添加過動態(tài)路由了,如果沒有,則先獲取數(shù)據(jù)進行添加路由。(router.beforeEach也會做登錄等攔截,這里省略)
import store from '@/store'
//這里我用vuex的一個變量 asyncRoutestMark 來標識是否拼接過路由
router.beforeEach((to, from, next) => {
if (!store.state.asyncRoutestMark) {
// navigationList 是上面模擬接口返回的數(shù)據(jù)
// 這里將新的路由都作為 home 的子路由(實際開發(fā)根據(jù)情況)
// 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(), '查看現(xiàn)有路由')
store.commit('setAsyncRoutestMark', true) // 添加路由后更改標識為true
next({ ...to, replace: true }) //路由進行重定向放行
} else {
next()
}
})利用router.getRoutes()方法查看現(xiàn)有路由,我們將會看到根據(jù)新的路由添加進去了。
這樣我們就實現(xiàn)了動態(tài)路由啦!
動態(tài)側(cè)邊菜單欄

- 這是我們要實現(xiàn)的效果,根據(jù)接口數(shù)據(jù)動態(tài)渲染,不論層級多少都可以自動渲染,一級菜單,二級菜單,三級甚至更多(不過一般最多只到三級哈哈)。
很多組件庫都可以實現(xiàn)這個功能,這里我們將使用 Ant Design of Vue 組件庫的內(nèi)嵌菜單組件(如下圖)去實現(xiàn),有父菜單,子菜單,父級菜單的是用 a-sub-menu 包裹,子菜單的是直接使用 a-menu-item,大家可以去看文檔看一下組件的使用。

接口數(shù)據(jù):這里模擬接口的菜單數(shù)據(jù)(實際情況可能要進行數(shù)據(jù)結構格式的轉(zhuǎn)換)
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循環(huán)菜單數(shù)據(jù)數(shù)組,渲染組件庫 ant design of vue的菜單組件,這時分兩種情況,
- 如果有children,那么渲染a-sub-menu(父級菜單),并包裹自身組件,把children數(shù)據(jù)傳遞給調(diào)用的自身組件,也就是遞歸調(diào)用組件自身,那么調(diào)用的自身組件就會重復上面邏輯的判斷,直到?jīng)]有children,也就是遇到了第二種情況,結束遞歸調(diào)用。
- 如果沒有children,那么直接顯示 a-menu-item (子菜單)
下面為菜單組件,組件名為MenuList,遞歸調(diào)用的時候要用到組件名,以達到根據(jù)不同數(shù)據(jù)渲染菜單的情況
沒有圖標版本
<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>效果如下

有圖標版本
圖標是根據(jù)接口數(shù)據(jù)的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>效果如下:

這樣我們就實現(xiàn)了動態(tài)側(cè)邊菜單欄啦!
總結
到此這篇關于如何利用Vue3管理系統(tǒng)實現(xiàn)動態(tài)路由和動態(tài)側(cè)邊菜單欄的文章就介紹到這了,更多相關Vue3動態(tài)路由和動態(tài)側(cè)邊菜單欄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue?webpack打包原理解析(全網(wǎng)最新最全)
webpack是讓我們可以進行模塊化開發(fā),并且會幫助我們處理模塊間的依賴關系,這篇文章主要介紹了vue?webpack打包原理,本篇介紹的有點長,希望大家耐心閱讀2023-02-02
vue3點擊出現(xiàn)彈窗后背景變暗且不可操作的實現(xiàn)代碼
這篇文章主要介紹了vue3點擊出現(xiàn)彈窗后背景變暗且不可操作的實現(xiàn)代碼,本文通過實例代碼圖文相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08
vue element-ui 綁定@keyup事件無效的解決方法
遇到vue element-ui 綁定@keyup事件無效的問題怎么解決?下面小編就為大家分享一篇vue element-ui 綁定@keyup事件無效的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03
vue-resource + json-server模擬數(shù)據(jù)的方法
本篇文章主要介紹了vue-resource + json-server模擬數(shù)據(jù)的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11
vue.js將時間戳轉(zhuǎn)化為日期格式的實現(xiàn)代碼
這篇文章主要介紹了vue.js將時間戳轉(zhuǎn)化為日期格式的實現(xiàn)代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-06-06

