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