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

目录
  • 前言
  • 用正则匹配出所有的h标签并且保存在数组中
  • 封装函数,将数组中的内容变成父子结构
  • 封装递归组件fold-item(在使用之前不要忘了导入自己哦)
  • 在foldMenu中使用递归组件
  • 使用效果

前言

在写我的个人博客网站,用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递归目录内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vuejs使用递归组件实现树形目录的方法

    上篇文章我提到了通讯录的开发,里面的目录使用了vue的递归组件实现的树形目录,这篇文章就来讲讲如何实现树形目录吧! 首先实现效果如下,觉得菜单还是比较nice的是吧: 这边数据调用的是数据库的数据的,需要数据库进行数据的构造,这里涉及到java的构造多叉树的知识,后续我会另外写一篇文章详细讲解,这里讲下前端. 数据可以先构造json使用,这里用到的格式大概如下,以childList来嵌套子菜单: { id:YH, name:银行, pid:0, childList:[{ id:YH******,

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

    目录 前言 用正则匹配出所有的h标签并且保存在数组中 封装函数,将数组中的内容变成父子结构 封装递归组件fold-item(在使用之前不要忘了导入自己哦) 在foldMenu中使用递归组件 使用效果 前言 在写我的个人博客网站,用MarkDownIt将md解析成html时,我一直在想,怎么才能实现官方文档他们那些可折叠的目录结构呢?我有那么多标题(h1...h5),而且有的文章是只有h2或者h3的,难道我要在目录组件里面一个个v-if来渲染这些标题达到目录的效果嘛?这个问题在我某一天看vue文档

  • Vue一个案例引发的递归组件的使用详解

    今天我们继续使用 Vue 的撸我们的实战项目,只有在实战中我们才会领悟更多,光纸上谈兵然并卵,继上篇我们的 <Vue一个案例引发的动态组件与全局事件绑定总结> 之后,今天来聊一聊我们如何在项目中使用递归组件. 信息的分类展示列表 这次我们主要是实现一个信息的分类展示列表存在二级/三级的分类,如下如所示: 看到这个很多人会想到这个实现起来很简单啊,来个嵌套循环不就完事了. 对,你说的没错,事实就是这样简单.那么就先来看看这么简单的列表怎么实现的,然后这个方案的劣势在哪里. 首先看看我们的数据格式

  • Vue使用zTree插件封装树组件操作示例

    本文实例讲述了Vue使用zTree插件封装树组件操作.分享给大家供大家参考,具体如下: 1.通过npm安装jquery npm install jquery --save-dev 2.在build/webpack.base.conf文件当中引入jquery module.exports = { ... resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': reso

  • vue+axios+element ui 实现全局loading加载示例

    实现全局loading加载 分析需求,我们只需要在请求发起的时候开始loading,响应结束的时候关闭loading,就这么简单 对不对? import axios from 'axios'; import { Message, Loading } from 'element-ui'; import Cookies from 'js-cookie'; import router from '@/router/index' let loading //定义loading变量 function st

  • vue之将echart封装为组件

    最近的新项目里,有大量数据图表类的需求,为了增强代码的复用性,减少冗余,我开始思考如何将echart封装为组件调用.本文将会以雷达图为案例,一步步讲解在vue项目中如何使用echart,如何将其封装为能重复调用的组件. 阅读之前,可以先看看我之前的一些文章,这样能更好的理解这次的内容: [使用vue-cli(vue脚手架)快速搭建项目]://www.jb51.net/article/140498.htm [vue之父子组件间通信实例讲解(props.$ref . $emit )]:www.jb5

  • Vue开发之封装分页组件与使用示例

    本文实例讲述了Vue开发之封装分页组件与使用.分享给大家供大家参考,具体如下: 使用elementui中的el-pagination来封装分页组件 pagination.vue: <template> <div class="pagination"> <el-pagination small class="text-center" @size-change="handleSizeChange" @current-ch

  • vue3 封装自定义组件v-model的示例

    首先要注意 vue3中 v-model 默认绑定的变量名变了,从原理的 value 改成了 modelValue,如果要改变变量的值,要执行一个事件 this.$emit("update:modelValue", value); <template> <div class="inline"> <input :type="password ? 'password' : 'text'" ref="input&q

  • vue基于element的区间选择组件

    公司的系统中,产品经理在设计时经常要求对某个字段进行区间阈值设置或者作为筛选条件.但是苦于element中没有非常契合的组件(slider组件并不支持两端均能设定),于是自己动手造了一个. 成果 最终的展示效果如下: 需求 这里以项目的需求为例,基本的需求如下: 分为左右值,包含左右值,正整数 左侧必须大于等于1,右侧不得大于100000,右侧值必须不小于左侧 默认:左侧20,右侧100000,均必填 失焦校验 页面和表单校验结构一样: <el-form ref="form" :

  • Vue结合原生js实现自定义组件自动生成示例

    就目前三大前端主流数据驱动框架(vue,ng,react)而言,均具有创建自定义组件的api,但都是必须先做到事先写好挂载点,这个挂载点可以是原有静态元素标签也可以是自定义模板:对于多种组件通过同一数据流生成的,如果事先在页面上写好挂载点(mounted),然后通过dom操作去动态添加,会遇到类似这样一条错误提示信息:Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.(-).这又是为何呢,下一

  • Vue.js弹出模态框组件开发的示例代码

    前言 在开发项目的过程中,经常会需要开发一些弹出框效果,但原生的alert和confirm往往都无法满足项目的要求.这次在开发基于Vue.js的读书WebApp的时候总共有两处需要进行提示的地方,因为一开始就没有引入其他的组件库,现在只好自己写一个模态框组件了.目前只是一个仅满足当前项目需求的初始版本,因为这个项目比较简单,也就没有保留很多的扩展功能.这个组件还是有很多扩展空间的,可以增加更多的自定义内容和样式.这里只介绍如何去开发一个模态框组件,有需要进行更多扩展的,可以根据自己的需求自行开发

随机推荐