TypechoJoeTheme

香草物语

统计
登录
用户名
密码
/
注册
用户名
邮箱
输入密码
确认密码

提取Html内容生成文章目录

Laughing博主
2024-07-21
/
0 评论
/
189 阅读
/
490 个字
/
百度已收录
07/21
本文最后更新于2024年07月21日,已超过59天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!

最近在开发一款在线知识库系统,为了方便使用,提供了两种编辑器,一种是基于markdown的,一种是基于富文本的。

基于markdown的编辑器,我们使用了MavonEditor插件,同时也是使用该插件进行markdown内容的展示,这个插件自带了目录功能,我们可以直接使用,感兴趣的可以看一下Vue使用mavon-editor插件实现Markdown文件编辑及预览

为了保证使用体验的一致性,基于富文本编辑器的内容,我们也给他添加一个目录功能,目录结构的展示我们使用elementUI框架的el-tree组件。

template代码

template代码比较简单,因为是基于elementUI框架的el-tree组件的,所以需要先安装elementUI

<el-tree class="toc-tree" ref="tree" node-key="uuid" :data="tocTreeData" :props="tocDefaultProps" v-if="tocTreeData && tocTreeData.length>0" default-expand-all>
  <div class="custom-tree-node" slot-scope="{ node, data }">
    <div @click="toDiv(data)">{{ data.text }}</div>
  </div>
</el-tree>

data代码

其实看到上面template的代码,我们大概能猜测到data里面需要的内容

tocTreeData: [],
tocDefaultProps: {
  label: 'text',
  children: 'children'
},

tocTreeData是我们存储的目录树形的结构

tocDefaultPropsel-tree组件用来配置展示内容及子节点的。

js代码

getCatalog()是入口方法,当我们在前端完成富文本内容的渲染后,就可以调用此方法,创建目录数据,进行展示。当然,提取目录的层级是根据我们的<h>标签进行提取的,可以自己定义提取的深度,比如我这里提取到了<h6>

toDiv()是点击目录时,用于页面滚动到对应位置的方法。

getCatalog() {
  const h = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
  const elements = document.querySelectorAll(h)
  let hElements = []
  for (const key of elements) {
    if (h.indexOf(key.localName) > -1) {
      let text
      if (key.children && key.children.length) {
        text = this.getText(key.children)
      } else {
        text = key.innerHTML
      }
      hElements.push({
        hLevel: parseInt(key.localName[1]),
        text,
        id: key.localName,
        uuid: key.id,
        offsetTop: key.offsetTop
      })
    }
  }
  this.tocTreeData = this.toTree(hElements)
},

getText(arr) {
  let result = null
  if (!arr.length) return
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].children && arr[i].children.length) {
      result = this.getText(arr[i].children)
    } else {
      result = arr[i].innerHTML
    }
  }
  return result
},
toTree(flatArr) {
  const tree = []
  const copyArr = flatArr.map(function(item) {
    return item
  })

  // 根据指定级别查找该级别的子孙级,并删除掉已经查找到的子孙级
  const getChildrenByLevel = function(currentLevelItem, arr, level) {
    if (!currentLevelItem) {
      return
    }
    // 将level值转成负数,再进行比较
    const minusCurrentLevel = -currentLevelItem.hLevel
    const children = []
    let i = 0, len = arr.length
    for (; i < len; i++) {
      const levelItem = arr[i]
      if (-levelItem.hLevel < minusCurrentLevel) {
        children.push(levelItem)
      } else {
        // 只找最近那些子孙级
        break
      }
    }
    // 从数组中删除已经找到的那些子孙级,以免影响到其他子孙级的查找
    if (children.length > 0) {
      arr.splice(0, children.length)
    }
    return children
  }

  const getTree = function(result, arr, level) {
    // 首先将数组第一位移除掉,并添加到结果集中
    let currentItem = arr.shift()

    currentItem.level = level
    result.push(currentItem)
    while (arr.length > 0) {
      if (!currentItem) {
        return
      }
      // 根据当前级别获取它的子孙级
      const children = getChildrenByLevel(currentItem, arr, level)
      // 如果当前级别没有子孙级则开始下一个
      if (children.length === 0) {
        currentItem = arr.shift()
        currentItem.level = level
        if (currentItem) {
          result.push(currentItem)
        }
        continue
      }
      currentItem.children = []
      // 查找到的子孙级继续查找子孙级
      getTree(currentItem.children, children, level + 1)
    }
  }
  getTree(tree, copyArr, 1)
  return tree
},
toDiv(data) {
  document.getElementById('contentMainId').scrollTop = data.offsetTop - 20
},
朗读
赞(0)
赞赏
感谢您的支持,我会继续努力哒!
版权属于:

香草物语

本文链接:

https://www.xiangcaowuyu.net/web/extract-html-content-to-generate-article-directory.html(转载时请注明本文出处及文章链接)

评论 (0)