公司项目需要写帮助中心,帮助中心内为用户提供使用手册,需要读取md文件。项目前端实现为vue3+ts,引入的md解析插件为v-md-editer,但是只引入了预览模式,所以没有插件自带的目录功能,需要自己实现。

vue实现读取md:

<el-row>
    <el-col :span="6">
        <div v-for="anchor in titles" :style="{ padding: `10px 0 10px ${anchor.indent * 20}px` }" @click="handleAnchorClick(anchor)" :key="anchor">
            <a style="cursor: pointer">{{ anchor.title }}</a>
        </div>
    </el-col>
    <el-col :span="18" ref="textAreaRef">
        <div class="guide-text">
            <v-md-preview :text="markDown.text" ref="preview"></v-md-preview>
        </div>
    </el-col>
</el-row>

页面代理 

  const { proxy }: any = getCurrentInstance()

ts实现生成目录

  const buildDirectory = () => {

    // preview为v-md-preview标签绑定的ref
    // v-md会将md文件内标题转换为html的h1-h6标签
    const anchors = proxy.$refs.preview.$el.querySelectorAll('h1,h2,h3,h4,h5,h6')
    titles.value = Array.from(anchors).filter((title: any) => !!title.innerText.trim())

    if (!titles.value.length) {
      proxy.titles = []
      return
    }
    const hTags = Array.from(new Set(titles.value.map((title: any) => title.tagName))).sort()

    proxy.titles = titles.value.map((el: any) => ({
      title: el.innerText,
      lineIndex: el.getAttribute('data-v-md-line'),
      indent: hTags.indexOf(el.tagName)
    }))
  }

实现目录跳转:

  const handleAnchorClick = (anchor: any) => {
    const { preview, textAreaRef } = proxy.$refs
    const { lineIndex } = anchor

    // 目标行位置
    const targetPosition = preview.$el.querySelector(`[data-v-md-line="${lineIndex}"]`).getBoundingClientRect().top
    // v-md主体位置
    const bodyPosition = preview.$el.querySelector('.vuepress-markdown-body').getBoundingClientRect().top
    // 以guide-text为父元素,vuepress-markdown-body为子元素进行跳转
    textAreaRef.$el.querySelector('.guide-text').scrollTop = targetPosition - bodyPosition
  }

跳转这里踩了好几个坑

1.对于html原生标签和引入的插件,获取其元素的方法又一点点差别

以ref为preview为例

原生标签:直接用$refs.preview  获取元素

插件:$refs.preview.$el 获取元素

2.scrollTop方法

  1. 父,子元素需设置高度,并且子元素高度必须大于父元素,这一点应该很好理解,如果子元素高度始终小于父元素,那么无论怎么设置scrollTop的值都不可能大于0
  2. 父元素需设置overflow: scroll 或 overflow-y:scroll,设置完这个之后父元素才能顺利的加载出滚动条,并成功的设置滚动高度
Logo

前往低代码交流专区

更多推荐