Vue冷門(mén)技巧遞歸組件實(shí)踐示例詳解
痛點(diǎn)引出
在平時(shí)的開(kāi)發(fā)當(dāng)中,渲染側(cè)邊欄導(dǎo)航菜單有時(shí)會(huì)遇到過(guò)需要側(cè)邊欄有多層甚至無(wú)限層級(jí)的問(wèn)題。此時(shí)更優(yōu)雅的方式便是使用遞歸組件
<el-menu> <template slot="title"> <i class="el-icon-location"></i> <span>菜單</span> </template> <el-submenu index="1-1"> <template slot="title">子菜單</template> <el-menu-item index="1-1-1">子菜單選項(xiàng)1</el-menu-item> <el-submenu index="1-1-2"> <template slot="title">子菜單的子菜單</template> <el-menu-item index="1-1-2-1">子菜單的子菜單的選項(xiàng)1</el-menu-item> </el-submenu> </el-submenu> </el-submenu> </el-menu>
可以看到這部分重復(fù)的代碼可以完全抽離出來(lái)做單獨(dú)的組件。
<el-submenu> <el-menu-item></el-menu-item> ... </el-submenu>
那么問(wèn)題來(lái)了,在一層當(dāng)中又有重復(fù)的submenu怎么辦?顯然這個(gè)層級(jí)是需要?jiǎng)討B(tài)生成的。比如:
<el-submenu> <el-menu-item></el-menu-item> ... <el-submenu> <el-menu-item></el-menu-item> ... <el-submenu> <el-menu-item></el-menu-item> ... //這里省略很多很多層 </el-submenu> </el-submenu> </el-submenu>
很明顯,這里需要可以用遞歸(recursive) 的思想來(lái)解決, 那么在template模版當(dāng)中有辦法做這樣的組件嗎?答案當(dāng)然是可以,template模版語(yǔ)法也是支持遞歸。
源碼中的體現(xiàn)
先找找源碼,我們?cè)趕rc/core/global-api.ts當(dāng)中找到initExtend函數(shù),這個(gè)函數(shù)是initGlobalAPI的一個(gè)執(zhí)行步驟,每個(gè)組件創(chuàng)建的時(shí)候都會(huì)去調(diào)用。
可以看到如果命中name,則會(huì)給自己的components的配置項(xiàng)當(dāng)中注冊(cè)自己,使得可以在編譯的時(shí)候可以識(shí)別到自己,從而在template模版語(yǔ)法當(dāng)中去使用。
組件示例封裝
首先定義數(shù)據(jù)結(jié)構(gòu)能描述這樣的菜單
[ { id: '1', title: '父菜單', children:[ {id:'1-1',title:'子選項(xiàng)',children:[]}, {id:'1-1',title:'子菜單',children:[ {id:...,title:...,children:...}, ... ]}, ... ] } ] 簡(jiǎn)單點(diǎn)描述就是 interface item:{ id: string, title: string, children: item[] | [] } item[]
然后開(kāi)始封裝組件
// RescursiveMenu.vue <template> <el-submenu :index="menuItem.id" v-if="menuItem.children.length"> <template slot="title">{{ menuItem.title }}</template> <template v-for="item in menuItem.children"> <RecursiveMenu :menuItem="item"/> </template> </el-submenu> <el-menu-item v-else>{{ menuItem.title }}</el-menu-item> </template> <script> export default { name:"RecursiveMenu", props: { menuItem: Object } } </script>
當(dāng)然這只是簡(jiǎn)單示例demo,后續(xù)根據(jù)業(yè)務(wù)需求相信難不倒各位看官。
使用:
<el-submenu> <template v-for="item in menuList.children"> <RecursiveMenu :menuItem="item" :key="item.id"/> </template> </el-submenu>
小擴(kuò)展
同樣的,vue也支持jsx/tsx語(yǔ)法 ,使用jsx則需要抽象需要重復(fù)的過(guò)程,封裝成渲染函數(shù)來(lái)實(shí)現(xiàn)遞歸,這里采用整個(gè)數(shù)組渲染過(guò)程抽象重復(fù),來(lái)實(shí)現(xiàn)遞歸。
//MyMenu.jsx export default { name:"RecursiveMenu", props: { menuList: Array, dafault:()=>([]) }, render(){ const recursiveRender = (menuList)=>{ return menuList.map((menuItem)=>{ return menuItem.children.length > 0 ? ( <elSubmenu index="{menuItem.id}"> <div slot="title">{menuItem.title}</div> {recursiveRender(menuItem.children)} </elSubmenu> ):( <elMenuItem key="{menuItem.id}">{ menuItem.title }</elMenuItem> ) } ) } return (<elMenu> {recursiveRender(this.menuList)} </elMenu> ) } }
當(dāng)然,如果想用jsx復(fù)刻上訴template當(dāng)中抽象的邏輯,可以寫(xiě)成這樣:
// RecursiveMenu.jsx export default { name:"RecursiveMenu", props: { menuItem: Object, dafault:()=>({}) }, render(){ const recursiveRender = (menuItem)=>{ return menuItem.children.length > 0 ? ( <elSubmenu index="{menuItem.id}"> <div slot="title">{menuItem.title}</div> {menuItem.children.map(children=>recursiveRender(children))} </elSubmenu> ):( <elMenuItem key="{menuItem.id}">{ menuItem.title }</elMenuItem> ) } return recursiveRender(this.menuItem) } }
總結(jié)
Vue當(dāng)中實(shí)現(xiàn)遞歸渲染,可以使用模版語(yǔ)法和jsx語(yǔ)法。而實(shí)現(xiàn)本質(zhì)上是抽象出重復(fù)的邏輯,以及找到遞歸退出點(diǎn)。
以上就是Vue冷門(mén)技巧遞歸組件實(shí)踐示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue 遞歸組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用vue點(diǎn)擊li,獲取當(dāng)前點(diǎn)擊li父輩元素的屬性值方法
今天小編就為大家分享一篇使用vue點(diǎn)擊li,獲取當(dāng)前點(diǎn)擊li父輩元素的屬性值方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09vue實(shí)現(xiàn)計(jì)數(shù)器簡(jiǎn)單制作
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)計(jì)數(shù)器簡(jiǎn)單制作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06vue基于better-scroll仿京東分類(lèi)列表
這篇文章主要為大家詳細(xì)介紹了vue基于better-scroll仿京東分類(lèi)列表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06vue3?ref實(shí)現(xiàn)響應(yīng)式的方法
這篇文章主要介紹了vue3的ref是如何實(shí)現(xiàn)響應(yīng)式的,我們講了ref是如何實(shí)現(xiàn)響應(yīng)式的,主要分為兩種情況:ref接收的是number這種原始類(lèi)型、ref接收的是對(duì)象這種非原始類(lèi)型,需要的朋友可以參考下2024-07-07詳解vue3中setUp和reactive函數(shù)的用法
這篇文章主要介紹了vue3函數(shù)setUp和reactive函數(shù)的相關(guān)知識(shí)及setup函數(shù)和reactive函數(shù)的注意點(diǎn),通過(guò)具體代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-06-06vue?element?ui?Select選擇器如何設(shè)置默認(rèn)狀態(tài)
這篇文章主要介紹了vue?element?ui?Select選擇器如何設(shè)置默認(rèn)狀態(tài)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,2023-10-10FastApi+Vue+LayUI實(shí)現(xiàn)前后端分離的示例代碼
本文主要介紹了FastApi+Vue+LayUI實(shí)現(xiàn)前后端分離的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11