如何利用Vue3管理系統(tǒng)實(shí)現(xiàn)動(dòng)態(tài)路由和動(dòng)態(tài)側(cè)邊菜單欄
前言
在做Vue管理系統(tǒng)的時(shí)候,都會(huì)遇到的一個(gè)需求:每個(gè)用戶的權(quán)限是不一樣的,那么他可以訪問的頁面(路由),可以操作的菜單選項(xiàng)是不一樣的,如果由后端控制,我們前端需要去實(shí)現(xiàn)動(dòng)態(tài)路由,動(dòng)態(tài)渲染側(cè)邊菜單欄。
動(dòng)態(tài)路由
- 在本示例管理系統(tǒng)中,由于每個(gè)用戶的權(quán)限不一樣,擁有的可以訪問的路由頁面也不一樣,用戶能訪問的路由頁面都是后端根據(jù)權(quán)限動(dòng)態(tài)配置的
- 我們前端需要根據(jù)后端接口返回的路由表去動(dòng)態(tài)增刪路由,從而生成這個(gè)用戶所擁有的路由。
重點(diǎn):實(shí)現(xiàn)動(dòng)態(tài)路由api
- router.addRoute() //應(yīng)用程序已經(jīng)運(yùn)行的時(shí)候添加路由
- router.removeRoute() // 應(yīng)用程序已經(jīng)運(yùn)行的時(shí)候刪除路由
定義共用的頁面路由(無論哪個(gè)用戶都會(huì)有的)
如無論什么用戶都可訪問登錄頁login,錯(cuò)誤頁面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ù)(這里進(jìn)行數(shù)據(jù)精簡(jiǎn),便于演示,實(shí)際情況可能要進(jìn)行數(shù)據(jù)結(jié)構(gòu)格式的轉(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: '設(shè)備管理', url: '/device' } ]
添加動(dòng)態(tài)路由進(jìn)去的時(shí)機(jī)(router.beforeEach)
利用全局前置守衛(wèi)router.beforeEach,在跳轉(zhuǎn)路由前先判斷是否已經(jīng)添加過動(dòng)態(tài)路由了,如果沒有,則先獲取數(shù)據(jù)進(jìn)行添加路由。(router.beforeEach也會(huì)做登錄等攔截,這里省略)
import store from '@/store' //這里我用vuex的一個(gè)變量 asyncRoutestMark 來標(biāo)識(shí)是否拼接過路由 router.beforeEach((to, from, next) => { if (!store.state.asyncRoutestMark) { // navigationList 是上面模擬接口返回的數(shù)據(jù) // 這里將新的路由都作為 home 的子路由(實(shí)際開發(fā)根據(jù)情況) // meta 是存儲(chǔ)一些信息,可以用于權(quán)限校驗(yàn)或其他 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) // 添加路由后更改標(biāo)識(shí)為true next({ ...to, replace: true }) //路由進(jìn)行重定向放行 } else { next() } })
利用router.getRoutes()方法查看現(xiàn)有路由,我們將會(huì)看到根據(jù)新的路由添加進(jìn)去了。
這樣我們就實(shí)現(xiàn)了動(dòng)態(tài)路由啦!
動(dòng)態(tài)側(cè)邊菜單欄
- 這是我們要實(shí)現(xiàn)的效果,根據(jù)接口數(shù)據(jù)動(dòng)態(tài)渲染,不論層級(jí)多少都可以自動(dòng)渲染,一級(jí)菜單,二級(jí)菜單,三級(jí)甚至更多(不過一般最多只到三級(jí)哈哈)。
很多組件庫都可以實(shí)現(xiàn)這個(gè)功能,這里我們將使用 Ant Design of Vue 組件庫的內(nèi)嵌菜單組件(如下圖)去實(shí)現(xiàn),有父菜單,子菜單,父級(jí)菜單的是用 a-sub-menu 包裹,子菜單的是直接使用 a-menu-item,大家可以去看文檔看一下組件的使用。
接口數(shù)據(jù):這里模擬接口的菜單數(shù)據(jù)(實(shí)際情況可能要進(jìn)行數(shù)據(jù)結(jié)構(gòu)格式的轉(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: '設(shè)備管理', icon: 'icon-shebei', menuId: 2 } ]
重點(diǎn):組件遞歸
使用v-for循環(huán)菜單數(shù)據(jù)數(shù)組,渲染組件庫 ant design of vue的菜單組件,這時(shí)分兩種情況,
- 如果有children,那么渲染a-sub-menu(父級(jí)菜單),并包裹自身組件,把children數(shù)據(jù)傳遞給調(diào)用的自身組件,也就是遞歸調(diào)用組件自身,那么調(diào)用的自身組件就會(huì)重復(fù)上面邏輯的判斷,直到?jīng)]有children,也就是遇到了第二種情況,結(jié)束遞歸調(diào)用。
- 如果沒有children,那么直接顯示 a-menu-item (子菜單)
下面為菜單組件,組件名為MenuList,遞歸調(diào)用的時(shí)候要用到組件名,以達(dá)到根據(jù)不同數(shù)據(jù)渲染菜單的情況
沒有圖標(biāo)版本
<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>
效果如下
有圖標(biāo)版本
圖標(biāo)是根據(jù)接口數(shù)據(jù)的icon去匹配的,有多種方法,例如使用iconFont、svg、png,主要是去對(duì)應(yīng)圖標(biāo)的名字,這里使用組件庫提供的使用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>
效果如下:
這樣我們就實(shí)現(xiàn)了動(dòng)態(tài)側(cè)邊菜單欄啦!
總結(jié)
到此這篇關(guān)于如何利用Vue3管理系統(tǒng)實(shí)現(xiàn)動(dòng)態(tài)路由和動(dòng)態(tài)側(cè)邊菜單欄的文章就介紹到這了,更多相關(guān)Vue3動(dòng)態(tài)路由和動(dòng)態(tài)側(cè)邊菜單欄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue全家桶實(shí)踐項(xiàng)目總結(jié)(推薦)
本篇文章主要介紹了Vue全家桶實(shí)踐項(xiàng)目總結(jié)(推薦),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11淺談在vue項(xiàng)目中如何定義全局變量和全局函數(shù)
本篇文章主要介紹了淺談在vue項(xiàng)目中如何定義全局變量和全局函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10VUE項(xiàng)目中引入vue-router的詳細(xì)過程
vue-router 也叫 vue 路由,根據(jù)不同的路徑,來執(zhí)行不同的組件,這篇文章主要介紹了VUE項(xiàng)目中引入vue-router,需要的朋友可以參考下2023-05-05vue?webpack打包原理解析(全網(wǎng)最新最全)
webpack是讓我們可以進(jìn)行模塊化開發(fā),并且會(huì)幫助我們處理模塊間的依賴關(guān)系,這篇文章主要介紹了vue?webpack打包原理,本篇介紹的有點(diǎn)長(zhǎng),希望大家耐心閱讀2023-02-02vue3點(diǎn)擊出現(xiàn)彈窗后背景變暗且不可操作的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue3點(diǎn)擊出現(xiàn)彈窗后背景變暗且不可操作的實(shí)現(xiàn)代碼,本文通過實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08vue element-ui 綁定@keyup事件無效的解決方法
遇到vue element-ui 綁定@keyup事件無效的問題怎么解決?下面小編就為大家分享一篇vue element-ui 綁定@keyup事件無效的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-03-03vue-resource + json-server模擬數(shù)據(jù)的方法
本篇文章主要介紹了vue-resource + json-server模擬數(shù)據(jù)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11vue.js將時(shí)間戳轉(zhuǎn)化為日期格式的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue.js將時(shí)間戳轉(zhuǎn)化為日期格式的實(shí)現(xiàn)代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-06-06