Vue遞歸實(shí)現(xiàn)樹形菜單方法實(shí)例
什么是樹形菜單還是要簡(jiǎn)單的啰嗦一下,比如:

上圖是截圖自elementui的實(shí)例,實(shí)現(xiàn)方式是用文檔結(jié)構(gòu)(類似像原生Dom文檔結(jié)構(gòu)的寫法)的方式,好處就是很靈活,可以方便的自定義,作為一個(gè)通用視圖組件庫(kù)這是正確的做法。
在實(shí)際的企業(yè)應(yīng)用中,菜單要比這復(fù)雜很多,層次也要多很多,如果我們采取手動(dòng)編寫文檔結(jié)構(gòu)的方式,會(huì)導(dǎo)致代碼亢長(zhǎng),閱讀和維護(hù)都很低效。毫無疑問所有Vuer都會(huì)想到用一個(gè)數(shù)據(jù)結(jié)構(gòu)來驅(qū)動(dòng)文檔結(jié)構(gòu)。vue-router的數(shù)據(jù)結(jié)構(gòu)恰恰就是完美的嵌套層次結(jié)構(gòu)(樹結(jié)構(gòu)),同時(shí)vue文檔中也提到了遞歸組件,基于這兩點(diǎn),我們來擼碼,不過這次有所不同,我們選擇使用render函數(shù)來實(shí)現(xiàn),而不是在模板中遞歸。
數(shù)據(jù)結(jié)構(gòu):vue-router的數(shù)據(jù)結(jié)構(gòu)
const routes = [
{
name: 'home',
path: '/home',
meta: { text: '首頁(yè)' }
},
{
name: 'inner',
path: '/inner',
meta: { text: '內(nèi)部平臺(tái)' },
children: [
{
name: 'oa',
path: 'oa',
meta: { text: 'OA' }
},
{
name: 'jira',
path: 'jira',
meta: { text: 'Jira' }
},
{
name: 'wiki',
path: 'wiki',
meta: { text: 'Wiki' }
},
{
name: 'caiwu',
path: 'caiwu',
meta: { text: '財(cái)務(wù)' },
children: [
{
name: 'chailv',
path: 'chailv',
meta: { text: '差旅' }
},
{
name: 'richang',
path: 'richang',
meta: { text: '日常' },
children: [
{
name: 'taxi',
path: 'taxi',
meta: { text: '交通' }
},
{
name: 'tel',
path: 'tel',
meta: { text: '通信' }
}
]
}
]
}
]
},
{
name: 'sec',
path: '/sec',
meta: { text: '審核' },
children: [
{
name: 'acl',
path: '/acl',
meta: { text: 'ACL' }
}
]
}
]
組件實(shí)現(xiàn):
先看看render函數(shù),其中包含一個(gè)遞歸函數(shù)elements:
render (r) {
return r(
'el-menu',
{
props: {
backgroundColor: "#545c64",
textColor: "#fff",
activeTextColor: "#ffd04b"
},
on: {
select: this.onSelect
}
},
this.elements(this.routes, r)
)
}
elements函數(shù):
elements (routes, r) {
return routes
.map(route => {
if (!route.paths) route.paths = []
if (route.children && route.children.length) {
return r(
'el-submenu',
{
props: {
index: route.name
}
},
[
r(
'span',
{
slot: 'title'
},
[
route.meta.text
]
),
this.elements(route.children, r)
]
)
} else if (route.path) {
return r(
'el-menu-item',
{
props: {
index: route.name
}
},
[
route.meta.text
]
)
} else {
return null
}
})
.filter(item => item)
}
最終效果:

完整代碼示例請(qǐng)戳:https://codepen.io/360vislab/pen/GQqBve
總結(jié):
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
vue3中的reactive函數(shù)聲明數(shù)組方式
這篇文章主要介紹了vue3中的reactive函數(shù)聲明數(shù)組方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
Vue?項(xiàng)目的成功發(fā)布和部署的實(shí)現(xiàn)
本文主要介紹了Vue?項(xiàng)目的成功發(fā)布和部署的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
Vue3?<script?setup?lang=“ts“>?的基本使用
<script setup>?是在單文件組件 (SFC) 中使用?composition api?的編譯時(shí)語法糖,本文主要講解<script setup>?與?TypeScript?的基本使用,感興趣的朋友跟隨小編一起看看吧2022-12-12
淺談一下Vue生命周期中mounted和created的區(qū)別
每一個(gè)vue實(shí)例從創(chuàng)建到銷毀的過程,就是這個(gè)vue實(shí)例的生命周期,在這個(gè)過程中,他經(jīng)歷了從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載Dom、渲染→更新→渲染、卸載等一系列過程,那么這些過程中,具體vue做了些啥,我們今天來了解一下2023-05-05
vue中使用vue-pdf組件實(shí)現(xiàn)文件預(yù)覽及相應(yīng)報(bào)錯(cuò)解決
在需求中,經(jīng)常遇見pdf的在線預(yù)覽效果,很多pdf插件不支持vue3,或者是沒有集成翻頁(yè)放大縮小功能,比如vue-pdf,下面這篇文章主要給大家介紹了關(guān)于vue中使用vue-pdf組件實(shí)現(xiàn)文件預(yù)覽及相應(yīng)報(bào)錯(cuò)解決的相關(guān)資料,需要的朋友可以參考下2022-09-09
關(guān)于Vue單頁(yè)面骨架屏實(shí)踐記錄
這篇文章主要給大家介紹了關(guān)于Vue單頁(yè)面骨架屏實(shí)踐的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-12-12
在vue項(xiàng)目中如何獲取視頻的時(shí)長(zhǎng)
這篇文章主要介紹了在vue項(xiàng)目中如何獲取視頻的時(shí)長(zhǎng),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04

