欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue3動態(tài)路由+菜單欄的實現(xiàn)示例

 更新時間:2024年04月02日 08:46:02   作者:湯達人  
在后臺管理系統(tǒng),可以根據(jù)登錄用戶的不同返回不同路由,頁面也會根據(jù)這些路由生成對應(yīng)的菜單,本文主要介紹了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)文章

最新評論