Vue结合Element-Plus封装递归组件实现目录示例

 更新时间:2022年04月12日 10:56:48   作者:想染上学习瘾  
本文主要介绍了Vue结合Element-Plus封装递归组件实现目录示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

前言

在写我的个人博客网站,用MarkDownIt将md解析成html时,我一直在想,怎么才能实现官方文档他们那些可折叠的目录结构呢?我有那么多标题(h1...h5),而且有的文章是只有h2或者h3的,难道我要在目录组件里面一个个v-if来渲染这些标题达到目录的效果嘛?这个问题在我某一天看vue文档的时候得到了解决。如下。

没错,递归组件可以解决我这个困惑,递归无非就是自己调用自己,我们编写好合理的组件渲染逻辑之后,在组件内部自己调用自己,这就是递归组件,接下来请看我的解决步骤吧!

用正则匹配出所有的h标签并且保存在数组中

//这里的str是用MarkdownIt解析生成的html字符串
  const menu = [...str.matchAll(/<h.*>.*</h.>/g)]

效果如下

封装函数,将数组中的内容变成父子结构

//我的每个菜单的类型
class menuItem {
  title: string
  children?: menuItem[]
  type: number   //type为1表示是h1标签
  index: number    //index表示是type对应的第几个h标签
  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标签
  const arr: menuItem[] = []
  const arrIndex: number[] = new Array(7).fill(0)
  // 用于保存前一个层的结点。例如我当前遍历的是type=3的item,那么我需要知道它所属于哪个type=2的item
  // 如果有就添加到它的children中,如果没有就添加到pre[3]中
  const pre = new Array(7).fill(null)
  //记录h min是哪个标签(例如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]++)

    //判断当前type-1项有没有内容,有的话就加入到前一个种类的children中去
    if (pre[type - 1]) {
      pre[type - 1].children.push(menuitem)
    }
    //重置当前type的项
    pre[type] = menuitem
    minType = minType ?? type
    //如果是最小的h标签,就插入
    if (type === minType) {
      arr.push(menuitem)
    }
  }
  return arr
}

转换的arr结果如下,可以看到,数组中保存了两个顶层目录,children保存了内部的子目录。

封装递归组件fold-item(在使用之前不要忘了导入自己哦)

<script lang="ts" setup>
import foldItem from './foldItem.vue'   //导入自己
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>

使用效果

更复杂的目录结构也能胜任

到此这篇关于Vue结合Element-Plus封装递归组件实现目录示例的文章就介绍到这了,更多相关Vue Element-Plus递归目录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue组件间通信的实现方法讲解

    Vue组件间通信的实现方法讲解

    组件是vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互进行直接的引用,所以组件间的相互通信是非常重要的
    2023-01-01
  • 优化Vue项目编译文件大小的方法步骤

    优化Vue项目编译文件大小的方法步骤

    这篇文章主要介绍了优化Vue项目编译文件大小的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • Element-UI el-calendar样式如何修改日历

    Element-UI el-calendar样式如何修改日历

    这篇文章主要介绍了Element-UI el-calendar样式如何修改日历问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Vue 计数器的实现

    Vue 计数器的实现

    这篇文章主要介绍了Vue 计数器的实现,主要利用HTML实现步骤现在页面上简单实现一个计数器,内容简单且详细,需要的朋友可以参考一下
    2021-10-10
  • Electron 如何调用本地模块的方法

    Electron 如何调用本地模块的方法

    这篇文章主要介绍了Electron 如何调用本地模块的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02
  • Vuex的使用及知识点笔记

    Vuex的使用及知识点笔记

    这篇文章主要介绍了Vuex的使用及知识点笔记,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Vue路由传参及props解耦深入分析

    Vue路由传参及props解耦深入分析

    vue路由传参的使用场景一般都是应用在父路由跳转到子路由时,携带参数跳转,下面这篇文章主要给大家介绍了关于vue路由传参方式的方式总结及获取参数的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Vue3 setup的注意点及watch监视属性的六种情况分析

    Vue3 setup的注意点及watch监视属性的六种情况分析

    这篇文章主要介绍了Vue3 setup的注意点及watch监视属性的六种情况,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • vue+elementUI实现内嵌table的方法示例

    vue+elementUI实现内嵌table的方法示例

    本文主要介绍了vue+elementUI实现内嵌table的方法示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • 图文讲解vue的v-if使用方法

    图文讲解vue的v-if使用方法

    在本篇文章里我们给大家分享了关于vue的v-if使用方法的相关知识点,有兴趣的朋友们跟着学习下。
    2019-02-02

最新评论