vue-markdown 之 markdown-it, 以及 table of content 的实现:markdown-it-toc-and-anchor
1. npm install --save uslug markdown-it markdown-it-toc-and-anchor
2. 主要代码
-
<template> <div id="lab_exp_book"> ... ... <div class="directory_box"> <div class="directory_title">目录</div> <ul class="directory_ul"> <li v-for="(item, index) in tocShow" :key="index"> <div v-if="item.children.length===0"> <a :class="{active: curContentScrollTop===item.anchorY}" class="lab_section_class hover_change_color" @click="handleDirClick(item)" href="javascript:">{{item.nodeName}}</a> </div> <div v-else> <div :class="{active: curContentScrollTop===item.anchorY || (!item.anchorY && index === 0)}" class="lab_section_title hover_change_color" @click="handleDirClick(item)">{{item.nodeName}}</div> <ul class="lab_section_children"> <li v-for="(each, index) in item.children" :key="index"> <div v-if="each.children.length===0"> <a :class="{active: curContentScrollTop===each.anchorY}" class="lab_section_class hover_change_color" @click="handleDirClick(each)" href="javascript:">{{each.nodeName}}</a> </div> <div v-else> <div :class="{active: curContentScrollTop===each.anchorY}" class="lab_section_title hover_change_color" @click="handleDirClick(each)">{{each.nodeName}}</div> <ul class="lab_section_children"> <li v-for="(third, index) in each.children" :key="index"> <div> <a :class="{active: curContentScrollTop===third.anchorY}" class="lab_section_class hover_change_color" @click="handleDirClick(third)" href="javascript:">{{third.nodeName}}</a> </div> </li> </ul> </div> </li> </ul> </div> </li> </ul> <div class="directory_tips">开始学习后可阅读实验手册内容</div> </div> </div> <div class="right_book_content" ref="rightBookContent"> <div class="book_box" v-if="1"> <div class="lab_simple_content clearfix" v-html="htmlStr"> </div> </div> ... ... </div> </template> <script> import uslug from 'uslug' import MarkdownIt from 'markdown-it' import markdownItTocAndAnchor from 'markdown-it-toc-and-anchor' data () { return { mdStr: '相关md字符串', htmlStr: '', // 渲染到页面 tocArray: [], tocShow: [], // 渲染到页面 isFirstClickDir: true, curContentScrollTop: 2 } }, computed: { ...mapState({ labDirectory: state => state.lab.labDirectory }) }, watch: { tocArray: { deep: true, handler (newValue) { const oldArr = JSON.parse(JSON.stringify(newValue)) let tocArr = [] let cur1Arr = null let cur2Arr = null let cur3Arr = null let cur4Arr = null let cur5Arr = null oldArr.reduce((newArr, next) => { if (next.level === 2) { cur1Arr = JSON.parse(JSON.stringify(next)) cur1Arr.children = [] cur1Arr.nodeName = cur1Arr.content cur2Arr = cur1Arr.children tocArr.push(cur1Arr) } else if (next.level === 3) { cur3Arr = JSON.parse(JSON.stringify(next)) cur3Arr.children = [] cur3Arr.nodeName = cur3Arr.content cur4Arr = cur3Arr.children cur2Arr.push(cur3Arr) } else if (next.level === 4) { cur5Arr = JSON.parse(JSON.stringify(next)) cur5Arr.children = [] cur5Arr.nodeName = cur5Arr.content // cur6Arr = cur5Arr.children cur4Arr.push(cur5Arr) } return newArr }, []) this.tocShow = tocArr } } }, async mounted () { this.myConsole('_labExpBookInit') this._initLabExpBook() await this.$store.dispatch('getLabDirectory') }, methods: { _uslugify(x) { return uslug(x) }, _initLabExpBook () { let md = new MarkdownIt({ html: false, xhtmlOut: true, typographer: true }) md.use(markdownItTocAndAnchor, {slugify: this._uslugify}) this.htmlStr = md.set({ tocCallback: (tocMarkdown, tocArray, tocHtml) => { this.tocArray = tocArray } }).render(this.mdStr) }, handleDirClick(dirNode) { window.scrollTo(0, 502) if (this.isFirstClickDir) { this.isFirstClickDir = false this._initDirScrollPos() bindEventFunc(this.$refs.rightBookContent, 'scroll', () => { this.curContentScrollTop = this.$refs.rightBookContent.scrollTop }) } this.$refs.rightBookContent.scrollTo({ top: dirNode.anchorY, left: 0, behavior: 'smooth' }) }, _initDirScrollPos () { this.tocShow = this.tocShow.map((ele) => { myConsole(ele.anchor) this._addAnchorY(ele) if (ele.children.length > 0) { ele.children.forEach((each, i) => { myConsole(ele.children[i].anchor) this._addAnchorY(ele.children[i]) if (each.children.length > 0) { each.children.forEach((one, j) => { myConsole(ele.children[i].children[j].anchor) this._addAnchorY(ele.children[i].children[j]) }) } }) } return ele }) }, _addAnchorY (ele) { ele.anchorY = document.getElementById(ele.anchor).getBoundingClientRect().top - 120 } ... ... </script>
3. 效果截图
--------小尾巴
________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...