vue3動態(tài)路由+菜單欄的實現(xiàn)示例
動態(tài)路由
這里用vue3和vite來實現(xiàn)動態(tài)路由,點擊這里查看效果 源碼
使用場景
在后臺管理系統(tǒng),可以根據(jù)登錄用戶的不同返回不同路由,頁面也會根據(jù)這些路由生成對應(yīng)的菜單。這樣通過服務(wù)器就能控制一個用戶可以訪問的內(nèi)容了。
比如管理員可以看到服務(wù)器日志,可以進行系統(tǒng)設(shè)置,普通用戶就訪問不了這些頁面。
步驟
定義基礎(chǔ)路由表
有一些路由不需要登錄也能訪問的,比如login和404頁面,這些路由要提前在寫好并加入到router中。
編寫路由組件
所有的路由組件都要提前寫好放到/views目錄下
添加路由
定義addRoute()方法,在登錄后獲取服務(wù)器路由通過這個方法添加路由
生成菜單
路由的meta字段可以添加一些菜單相關(guān)的信息,比如菜單名、icon、排序之類的。遍歷路由列表,根據(jù)meta的信息就能生成對應(yīng)的菜單了
代碼
服務(wù)器路由數(shù)據(jù)
這里模擬服務(wù)器返回的數(shù)據(jù),為了方便只寫了一條路由,看源碼有更多示例。
meta的數(shù)據(jù)是自己定的,一定要跟后端對接好。
[ { path: '/user', component: 'DEFAULT_LAYOUT', meta: {menuName: '用戶', order: 1}, children: [ { path: 'info', name: 'userInfo', component: 'user/info', meta: {menuName: '個人中心'} } ] } ]
注意
- 只支持二級路由,也就是子路由下不能再有子路由
- 每個一級路由至少有一個子路由,即使你只想展示一個菜單。因為父路由需要顯示布局組件,子路由才是真正顯示內(nèi)容的地方。
- component: 'DEFAULT_LAYOUT'表示這個路由要使用的布局組件,需要提前定義好。
- meta: {menuName: '用戶', order: 1}menuName表示這個菜單的名稱,order表示菜單的排序,還可以添加其他內(nèi)容,比如
- 只有一個子路由不想生成二級菜單,就可以設(shè)置single: true
- 子路由的name,必須設(shè)置這個字段,而且整個路由中不能重復(fù),點擊一個菜單時需要用它來導航
- 子路由的component表示路由組件的位置,需要提前在/views目錄下把所有路由組件都寫好。比如這里的user/info
- 實際會導入import('@/views/user/info.vue')。注意:路徑之間必須用/隔開
- meta: {menuName: '個人中心'}子路由必須定義menuName,因為子路由會生成用戶可以點擊的菜單,沒有名稱的話就不會顯示了
添加路由
假設(shè)現(xiàn)在登錄成功,開始調(diào)用addRoute()方法添加路由,這個方法根據(jù)情況放在自己需要的地方,這里為了演示都放在一起了。
// /components/layout.vue import { ref } from 'vue' import { useRouter } from 'vue-router' // 這個布局組件需要自己提前定義好 import DEFAULT_LAYOUT from '@/components/layout.vue' const server_route = ref([]) const addRoute = async () => { // 如果本地沒有路由信息,就從服務(wù)器獲取 if (!server_route.value.length) { // 這里模擬從服務(wù)器獲取數(shù)據(jù),實際需要從后端獲取數(shù)據(jù) const { default: routes = [] } = await import('@/router/server_route') server_route.value = routes } // 把路由表的component字段轉(zhuǎn)成真實的路由 server_route.value.map((_route) => { if (_route.component === 'DEFAULT_LAYOUT') { _route.component = DEFAULT_LAYOUT } const children = _route.children // 根據(jù)字符串動態(tài)導入路由組件 if (Array.isArray(children) && children?.length > 0) { children.map((childRoute) => { const path = childRoute.component.split('/') if (path.length === 1) { childRoute.component = () => import(`@/views/${path}.vue`) } else { childRoute.component = () => import(`@/views/${path[0]}/${path[1]}.vue`) } }) } }) // 排序 server_route.value.sort((a, b) => (a?.meta?.order ?? 0) - (b?.meta?.order ?? 0)) // 循環(huán)添加路由 server_route.value.map((route) => router.addRoute(route)) }
從服務(wù)器獲取到的數(shù)據(jù)會保存到server_route里面,實際開發(fā)應(yīng)該保存到本地localStorage,否則刷新所有路由消失。
獲取到數(shù)據(jù)還不能用,因為component字段還是字符串,要轉(zhuǎn)成懶加載的形式導入組件才行。
// 把路由表的component字段轉(zhuǎn)成真實的路由 server_route.value.map((_route) => { if (_route.component === 'DEFAULT_LAYOUT') { // 設(shè)置布局組件,可以為項目設(shè)置多個布局,服務(wù)器只需要修改這里,前端就能顯示多種布局了 _route.component = DEFAULT_LAYOUT } const children = _route.children // 根據(jù)字符串動態(tài)導入路由組件 if (Array.isArray(children) && children?.length > 0) { children.map((childRoute) => { const path = childRoute.component.split('/') // 用vite提供的動態(tài)導入功能,根據(jù)字符串從views目錄下導入組件 // 參考:https://cn.vitejs.dev/guide/features.html#dynamic-import if (path.length === 1) { // 如果是單個vue文件 childRoute.component = () => import(`@/views/${path[0]}.vue`) } else { // 否則就是一個目錄 childRoute.component = () => import(`@/views/${path[0]}/${path[1]}.vue`) } }) } })
因為父組件的布局組件比較少,一般不用做懶加載全部導入進來,根據(jù)字符串選擇對應(yīng)的布局就行了。
子組件需要動態(tài)的導入。vite提供了根據(jù)變量動態(tài)導入模塊的方法。
如果component: 'user/info'
- 先const path = childRoute.component.split('/')拆分一下路徑,這時候path = ['user', 'info']
- 因為import()根據(jù)變量導入只能深入一層文件,如果直接導入user/info,這樣會報錯,需要先拆分然后再拼起來
- 然后根據(jù)path動態(tài)導入路由,并賦值給子路由的component字段。需要保證/views目錄下有這樣的組件
// 路徑必須以絕對路徑,相對路徑或@開頭,文件名結(jié)尾,vite官網(wǎng)有說明 // 不符合的話導入報錯 childRoute.component = () => import(`@/views/${path[0]}/${path[1]}.vue`)
如果component: 'welcome'
- 這時候組件的路徑就等于path = ['welcome']
- 然后動態(tài)導入
childRoute.component = () => import(`@/views/${path[0]}.vue`)
上面的代碼默認子路由下面沒有子路由了,如果有很多級路由的話,需要做更多的判斷。
經(jīng)過轉(zhuǎn)換已經(jīng)把component轉(zhuǎn)成真正的組件了,轉(zhuǎn)換后的server_route
import DEFAULT_LAYOUT from '@/components/layout.vue' server_route.value = [ { path: '/user', component: DEFAULT_LAYOUT, meta: {menuName: '用戶', order: 1}, children: [ { path: 'info', name: 'userInfo', component: () => import('@/views/user/info.vue'), meta: {menuName: '個人中心'} } ] } ]
這樣再排序一下然后就可以直接添加到router里面了
import { useRouter } from 'vue-router' const router = useRouter() // 排序 server_route.value.sort((a, b) => (a?.meta?.order ?? 0) - (b?.meta?.order ?? 0)) // 遍歷轉(zhuǎn)換好的路由表,添加路由 server_route.value.map((_route) => router.addRoute(_route))
生成菜單
有了路由數(shù)據(jù),下面可以生成菜單了,這里只對server_route服務(wù)器返回的數(shù)據(jù)生成菜單,本地定義的路由不會添加到菜單里面
<!-- /components/layout.vue --> <template> <div> <nav> <h1>菜單欄</h1> <div style="display: flex; gap: 50px; align-items: flex-end;"> <template v-for="menu in server_route"> <!-- 顯示多級菜單--> <div v-if="!menu.meta.single"> <h5>{{ menu.meta.menuName }}</h5> <button v-for="child in menu.children" @click="router.push({name: child.name})"> {{ child.meta.menuName }} </button> </div> <!-- 只顯示一級菜單--> <div v-else> <button @click="router.push({name: menu.children[0].name})">{{ menu.children[0].meta.menuName }}</button> </div> </template> </div> </nav> <hr> <button v-show="needAddRoutes" @click="login">模擬登錄獲取路由</button> <main> <router-view /> </main> </div> </template>
上面的代碼只是演示,實際開發(fā)應(yīng)該定義一個單獨的layout-aside組件專門渲染菜單。
總結(jié)
動態(tài)添加路由只要提前定義好服務(wù)器數(shù)據(jù),約定好格式,做起來還是很簡單的。只要能根據(jù)component字段正確的導入組件就沒什么大問題,
不過這只是一個簡單的示例,實際開發(fā)還是有很多情況要處理的。
到此這篇關(guān)于vue3動態(tài)路由+菜單欄的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)vue3動態(tài)路由+菜單欄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue 修改 data 數(shù)據(jù)問題并實時顯示的方法
今天小編就為大家分享一篇vue 修改 data 數(shù)據(jù)問題并實時顯示的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08element table跨分頁多選及回顯的實現(xiàn)示例
本文主要介紹了element table跨分頁多選及回顯的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02vue項目實現(xiàn)一鍵網(wǎng)站換膚效果實例(webpack-theme-color-replacer的使用)
換皮膚一般都是點擊一個按鈕彈出一些皮膚的選項,選中選項后皮膚生效,下面這篇文章主要給大家介紹了關(guān)于vue項目實現(xiàn)一鍵網(wǎng)站換膚效果的相關(guān)資料,文中主要介紹的是webpack-theme-color-replacer的使用,需要的朋友可以參考下2023-02-02vue ssr+koa2構(gòu)建服務(wù)端渲染的示例代碼
這篇文章主要介紹了vue ssr+koa2構(gòu)建服務(wù)端渲染的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03使用Vue Composition API寫出清晰、可擴展的表單實現(xiàn)
這篇文章主要介紹了使用Vue Composition API寫出清晰、可擴展的表單實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06vue內(nèi)置組件component--通過is屬性動態(tài)渲染組件操作
這篇文章主要介紹了vue內(nèi)置組件component--通過is屬性動態(tài)渲染組件操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07