vue動態(tài)的 BreadCrumb 組件el-breadcrumb ElementUI詳解
,本文通過圖文示例代碼相結合給大家介紹的非常詳細,需要的朋友可以參考下
vue 如何做一個動態(tài)的 BreadCrumb 組件 el-breadcrumb ElementUI
一、ElementUI 中的 BreadCrumb 定義
elementUI 中的 Breadcrumb 組件是這樣定義的
<template> <el-breadcrumb separator="/"> <el-breadcrumb-item :to="{ path: '/' }">主頁</el-breadcrumb-item> <el-breadcrumb-item>系統(tǒng)配置</el-breadcrumb-item> <el-breadcrumb-item>基礎配置</el-breadcrumb-item> <el-breadcrumb-item>自動登錄</el-breadcrumb-item> </el-breadcrumb> </template>
效果如圖:
二、實現(xiàn)原理
我們需要實現(xiàn)的是,讓它自己通過路由去填寫這部分內容
原理是根據(jù)當前路由值,拆分成多個段,然后通過路由 path 去匹配對應的路由名稱,再填入到上面的內容中即可。
比如:
1. 當前的路由值是 /system/normal-setup/auto-login
2. 通過拆分 /
生成一個數(shù)組
3. 依次匹配對應的路由名稱
得到這個數(shù)組之后,依次去路由列表中匹配對應的路由名稱
/system
系統(tǒng)配置/system/normal-setup
- 基礎配置
/system/normal-setup/auto-login
自動登錄
4. 結果
這樣就得到了一個 breadCrumb 數(shù)組,直接遍歷這個數(shù)組,顯示 BreadCrumb 即可
三、具體實現(xiàn)過程
知道了上面的實現(xiàn)原理,才會有具體的實現(xiàn)過程,這個過程還是有點麻煩的。
1. 處理路由數(shù)據(jù)
項目中用到的路由數(shù)據(jù)是這樣的樹形結構,路由數(shù)據(jù)的定義是這樣的,里面的 children 可以嵌套任意層:
interface MenuEntity { id?: number | null, parent_id: number, name: string, icon?: string, type: EnumMenuType, // 1->目錄 2->菜單 3->按鈕 4->外鏈 path: string, component?: string, visible: EnumMenuVisible, // 1->可見 2->隱藏 默認為1 redirect: string, sort: number, // 默認為 20 perm: string, // permission created_at?: string, updated_at?: string, children?: MenuEntity[] }
實際的數(shù)據(jù)是這樣的:
{ "name": "系統(tǒng)配置", "id": 10, "parent_id": -1, "type": 1, "path": "/system", "component": "", "visible": 1, "redirect": "", "perm": "", "sort": 100, "icon": "Setting", "created_at": "2024-02-26T14:55:12+08:00", "updated_at": "2024-02-26T16:12:34+08:00", "children": [ { "name": "基礎配置", "id": 12, "parent_id": -1, "type": 1, "path": "/system/normal-setup", "component": "", "visible": 1, "redirect": "", "perm": "", "sort": 10, "icon": "CreditCard", "created_at": "2024-02-26T15:20:15+08:00", "updated_at": "2024-02-26T16:11:56+08:00", "children": [ { "name": "自動登錄", "id": 13, "parent_id": 12, "type": 2, "path": "/system/normal-setup/auto-login", "component": "System/NormalSetup/AutoLoginSetup.vue", "visible": 1, "redirect": "", "perm": "", "sort": 30, "icon": "User", "created_at": "2024-02-26T15:24:18+08:00", "updated_at": "2024-05-17T14:11:52+08:00", "children": [] }, { "name": "系統(tǒng)更新", "id": 28, "parent_id": 12, "type": 2, "path": "/system/normal-setup/system-update", "component": "System/SystemUpdate.vue", "visible": 1, "redirect": "", "perm": "", "sort": 50, "icon": "UploadFilled", "created_at": "2024-02-26T16:19:49+08:00", "updated_at": "2024-05-17T14:11:39+08:00", "children": [] }, { "name": "申請廠家技術支持", "id": 29, "parent_id": 12, "type": 2, "path": "/system/normal-setup/factory-help", "component": "User/Space.vue", "visible": 1, "redirect": "", "perm": "", "sort": 40, "icon": "SuitcaseLine", "created_at": "2024-02-26T16:20:11+08:00", "updated_at": "2024-03-27T09:04:20+08:00", "children": [] } ] } ] }
為了好后續(xù)匹配 path 到路由名,需要將這個數(shù)據(jù)平化成一個數(shù)組,并構建一個 Map<path, RouteItem>
這樣的一個 Map 數(shù)據(jù),目的是當執(zhí)行下面操作時,取到對應的路由數(shù)據(jù)
flatMenuPathNameMap.get('/system') // 最終取到這樣的數(shù)據(jù) { "name": "系統(tǒng)配置", "id": 10, "parent_id": -1, "type": 1, "path": "/system", "component": "", "visible": 1, "redirect": "", "perm": "", "sort": 100, "icon": "Setting", "created_at": "2024-02-26T14:55:12+08:00", "updated_at": "2024-02-26T16:12:34+08:00", }
平化樹形數(shù)據(jù)、生成對應的 Map 數(shù)據(jù)結構:
/** * 菜單相關 * 這里是單獨放到了 pinia 中 */ export const useMenuStore = defineStore('menuStore', { state: () => ({ menus: [] as Array<RouteRecordRaw>, flatMenuArray: [] as Array<MenuEntity>, flatMenuPathNameMap: new Map<string, string>() }), actions: { generateMenuArrayAndMap(){ let menuString = localStorage.getItem('dataMenu') let menusCache = menuString ? JSON.parse(menuString) as Array<MenuEntity> : [] as Array<MenuEntity> let flatMenuArray = recursionMenuData(menusCache) this.flatMenuArray = flatMenuArray this.flatMenuPathNameMap = new Map(flatMenuArray.map(item => [item.path, item.name])) // 遞歸方法,平化菜單數(shù)據(jù) function recursionMenuData(menuArray: Array<MenuEntity>){ let tempArray: Array<MenuEntity> = [] menuArray.forEach(item => { if (item.children && item.children.length > 0){ tempArray = tempArray.concat(recursionMenuData(item.children)) // 添加本身,并去除 children 屬性 delete item.children tempArray.push(item) } else { tempArray.push(item) } }) return tempArray } }, } })
使用的時候
import {useMenuStore, useProjectStore} from "./pinia"; const storeMenu = useMenuStore() // 當執(zhí)行下面的操作時就會補全 storeMenu.flatMenuArray 和 storeMenu.flatMenuPathNameMap storeMenu.generateMenuArrayAndMap()
路由樹的基礎數(shù)據(jù)是這樣的:
平化后的路由數(shù)組是這樣的:
最終生成的 Map 數(shù)據(jù)是這樣的:
2. 拆分當前路由 path,并匹配
比如當前路由是 /system/normal-setup/auto-login
,把它通過 /
拆分之后就是這樣的結果
import {useRoute} from "vue-router"; const route = useRoute() let routeSectionArray = route.path.split('/').filter(item => item !== '') // 這樣拆分之后,前面會多出一個空白的 "" ,所以這里剔除了它
接下來要做的就是通過上面的 routerSectionArray
生成下面的幾個路由組合,再去之前生成的 Map 中匹配對應的路由名即可
/system
/system/normal-setup
/system/normal-setup/auto-login
匹配之后就是這樣的結果
/system
系統(tǒng)配置/system/normal-setup
- 基礎配置
/system/normal-setup/auto-login
自動登錄
代碼是這樣的:
import {useRoute} from "vue-router"; import {onMounted, ref} from "vue"; import {useMenuStore} from "@/pinia"; const storeMenu = useMenuStore() const route = useRoute() const breadCrumbArray = ref<Array<{name: string, path: string}>>([]) onMounted(()=>{ let routeSectionArray = route.path.split('/').filter(item => item !== '') console.log(routeSectionArray) routeSectionArray.forEach((_, index) => { let path = `/${routeSectionArray.slice(0,index + 1).join('/')}` let pathName = storeMenu.flatMenuPathNameMap.get(path) console.log('---',pathName, path) if (pathName){ breadCrumbArray.value.push({name: pathName, path: path}) } }) })
四、搭配其它組件構建頁面
弄好上面的 BreadCrumb 組件之后,就可以不用再管它內部的內容了,它會自動根據(jù)當前路由值生成對應的內容。
這樣我們就可以放心的把它放到頁面結構中了。
比如我的頁面主要結構是這樣的:
Toolerbar.vue
<template> <div class="tool-bar"> <div class="left"> <Breadcrumb/> <slot name="left"/> </div> <div class="center"> <slot name="center"/> </div> <div class="right"> <slot name="right"/> </div> </div> </template> <script setup lang="ts"> import Breadcrumb from "@/layout/Breadcrumb.vue"; </script> <style scoped lang="scss"> .tool-bar{ padding: 0 20px; align-items: center; min-height: 50px; display: flex; flex-flow: row wrap; justify-content: space-between; .left{ display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center; flex-shrink: 0; } .center{ display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center; flex-grow: 1; flex-shrink: 0; } .right{ display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center; flex-shrink: 0; } } </style>
Breadcrumb.vue
<template> <el-breadcrumb separator="/"> <el-breadcrumb-item :to="{ path: '/' }">主頁</el-breadcrumb-item> <el-breadcrumb-item v-for="item in breadCrumbArray" :key="item">{{ item.name }}</el-breadcrumb-item> </el-breadcrumb> </template> <script setup lang="ts"> import {useRoute} from "vue-router"; import {onMounted, ref} from "vue"; import {useMenuStore} from "@/pinia"; const storeMenu = useMenuStore() const route = useRoute() defineProps( { height: { // 高度 type: Number, default: 100 } }) const breadCrumbArray = ref<Array<{name: string, path: string}>>([]) onMounted(()=>{ let routeSectionArray = route.path.split('/').filter(item => item !== '') routeSectionArray.forEach((_, index) => { let path = `/${routeSectionArray.slice(0,index + 1).join('/')}` let pathName = storeMenu.flatMenuPathNameMap.get(path) console.log('---',pathName, path) if (pathName){ breadCrumbArray.value.push({name: pathName, path: path}) } }) }) </script> <style lang="scss" scoped> @import "../assets/scss/plugin"; </style>
實際頁面中使用時這樣:
<template> <Container> <Toolbar> <template #left> </template> <template #center> </template> <template #right> </template> </Toolbar> <Content> </Content> </Container> <template>
五、結果
到此這篇關于vue 如何做一個動態(tài)的 BreadCrumb 組件,el-breadcrumb ElementUI的文章就介紹到這了,更多相關vue動態(tài)的 BreadCrumb 組件內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue 重塑數(shù)組之修改數(shù)組指定index的值操作
這篇文章主要介紹了vue 重塑數(shù)組之修改數(shù)組指定index的值操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08Vue如何使用Promise.all()方法并行執(zhí)行多個請求
在Vue中,可以使用Promise.all()方法并行執(zhí)行多個異步請求,當所有請求都成功返回時,Promise.all()將返回一個包含所有請求結果的數(shù)組,如果其中任何一個請求失敗,則會觸發(fā)catch()方法并返回錯誤信息,這種方式可以顯著提高程序的性能和響應速度2025-01-01在vue中根據(jù)光標的顯示與消失實現(xiàn)下拉列表
這篇文章主要介紹了在vue中根據(jù)光標的顯示與消失實現(xiàn)下拉列表,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09