Vue結(jié)合Element-Plus封裝遞歸組件實(shí)現(xiàn)目錄示例
前言
在寫我的個人博客網(wǎng)站,用MarkDownIt將md解析成html時,我一直在想,怎么才能實(shí)現(xiàn)官方文檔他們那些可折疊的目錄結(jié)構(gòu)呢?我有那么多標(biāo)題(h1...h5),而且有的文章是只有h2或者h(yuǎn)3的,難道我要在目錄組件里面一個個v-if來渲染這些標(biāo)題達(dá)到目錄的效果嘛?這個問題在我某一天看vue文檔的時候得到了解決。如下。
沒錯,遞歸組件可以解決我這個困惑,遞歸無非就是自己調(diào)用自己,我們編寫好合理的組件渲染邏輯之后,在組件內(nèi)部自己調(diào)用自己,這就是遞歸組件,接下來請看我的解決步驟吧!
用正則匹配出所有的h標(biāo)簽并且保存在數(shù)組中
//這里的str是用MarkdownIt解析生成的html字符串 const menu = [...str.matchAll(/<h.*>.*</h.>/g)]
效果如下
封裝函數(shù),將數(shù)組中的內(nèi)容變成父子結(jié)構(gòu)
//我的每個菜單的類型 class menuItem { title: string children?: menuItem[] type: number //type為1表示是h1標(biāo)簽 index: number //index表示是type對應(yīng)的第幾個h標(biāo)簽 constructor( title: string, type: number, index: number, children: menuItem[] = [] ) { this.title = title this.children = children this.type = type this.index = index } } export default function (menu: any[]): any[] { //保存所有h min標(biāo)簽 const arr: menuItem[] = [] const arrIndex: number[] = new Array(7).fill(0) // 用于保存前一個層的結(jié)點(diǎn)。例如我當(dāng)前遍歷的是type=3的item,那么我需要知道它所屬于哪個type=2的item // 如果有就添加到它的children中,如果沒有就添加到pre[3]中 const pre = new Array(7).fill(null) //記錄h min是哪個標(biāo)簽(例如h1) let minType = null for (const item of menu) { const content = item[0] const type = parseInt(content[2]) const title = content.split(/<\/?h.>/)[1] const menuitem = new menuItem(title, type, arrIndex[type]++) //判斷當(dāng)前type-1項(xiàng)有沒有內(nèi)容,有的話就加入到前一個種類的children中去 if (pre[type - 1]) { pre[type - 1].children.push(menuitem) } //重置當(dāng)前type的項(xiàng) pre[type] = menuitem minType = minType ?? type //如果是最小的h標(biāo)簽,就插入 if (type === minType) { arr.push(menuitem) } } return arr }
轉(zhuǎn)換的arr結(jié)果如下,可以看到,數(shù)組中保存了兩個頂層目錄,children保存了內(nèi)部的子目錄。
封裝遞歸組件fold-item(在使用之前不要忘了導(dǎo)入自己哦)
<script lang="ts" setup> import foldItem from './foldItem.vue' //導(dǎo)入自己 defineProps({ item: { type: Object, default: () => ({}) } }) </script> <template> <!-- 如果有孩子,就渲染成sub-menu(折疊item)--> <template v-if="item.children.length"> <el-sub-menu :index="item.title"> <template #title> <div class="title" v-html="item.title"></div> </template> <fold-item v-for="i in item.children" :key="i.title" :item="i" ></fold-item> </el-sub-menu> </template> <!-- 否則就渲染成menu-item--> <template v-else> <el-menu-item :index="item.title" @click="scrollToItem(item)"> <template #title> <div class="title" v-html="item.title"></div> </template> </el-menu-item> </template> </template> <style lang="less" scoped> .title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } ::v-deep.el-menu-item { width: 220px; line-height: 30px; height: 30px; } ::v-deep.el-sub-menu { width: 220px; } ::v-deep .el-sub-menu__title { height: 30px; line-height: 30px; } </style>
在foldMenu中使用遞歸組件
<script lang="ts" setup> import foldItem from './foldItem.vue' defineProps({ menu: { type: Array, default: () => [] } }) </script> <template> <div class="menu-title">目錄</div> <el-menu> <!-- 使用遞歸組件 --> <fold-item v-for="item in menu" :key="item.title" :item="item"></fold-item> </el-menu> </template> <style lang="less" scoped> ::v-deep.el-menu { border: none; } .menu-title { text-align: center; margin-bottom: 10px; } </style>
使用效果
更復(fù)雜的目錄結(jié)構(gòu)也能勝任
到此這篇關(guān)于Vue結(jié)合Element-Plus封裝遞歸組件實(shí)現(xiàn)目錄示例的文章就介紹到這了,更多相關(guān)Vue Element-Plus遞歸目錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談vue中使用圖片懶加載vue-lazyload插件詳細(xì)指南
本篇文章主要介紹了淺談vue中使用圖片懶加載vue-lazyload插件詳細(xì)指南,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-10-10vue使用element-ui tabs切換echarts解決寬度100%方式
這篇文章主要介紹了vue使用element-ui tabs切換echarts解決寬度100%方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07詳談vue中router-link和傳統(tǒng)a鏈接的區(qū)別
這篇文章主要介紹了詳談vue中router-link和傳統(tǒng)a鏈接的區(qū)別,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07vue項(xiàng)目中實(shí)現(xiàn)圖片預(yù)覽的公用組件功能
小編接到查看影像的功能需求,根據(jù)需求,多個組件需要用到查看影像的功能,所以考慮做一個公用組件,通過組件傳值的方法將查看影像文件的入?yún)鬟^去。下面小編通過實(shí)例代碼給大家分享vue項(xiàng)目中實(shí)現(xiàn)圖片預(yù)覽的公用組件功能,需要的朋友參考下吧2018-10-10Antd-vue Table組件添加Click事件,實(shí)現(xiàn)點(diǎn)擊某行數(shù)據(jù)教程
這篇文章主要介紹了Antd-vue Table組件添加Click事件,實(shí)現(xiàn)點(diǎn)擊某行數(shù)據(jù)教程,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11vue+element+electron仿微信實(shí)現(xiàn)代碼
這篇文章主要介紹了vue+element+electron仿微信實(shí)現(xiàn),本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12利用vue3自己實(shí)現(xiàn)計(jì)數(shù)功能組件封裝實(shí)例
組件(Component) 是Vue.js最強(qiáng)大的功能之一,組件可以擴(kuò)展 HTML 元素,封裝可重用的代碼,這篇文章主要給大家介紹了關(guān)于利用vue3自己實(shí)現(xiàn)計(jì)數(shù)功能組件封裝的相關(guān)資料,需要的朋友可以參考下2021-09-09