背景
因为是markdown,所以用户可以随便写,像图一这种规规矩矩的标题 做成锚点很简单。
但是markdown里面 用户可以随便写,就会出现图二这种情况,这种情况下 antdv的anchor的带children嵌套的那种数组就不好实现了
图一
图二
方案
因此我们选择 把所有的项放到同一级,然后给不同的标题加class,通过css来做成这种有间距的效果
<script setup>
import { marked } from 'marked'
import { onMounted, computed, ref } from 'vue'
const anchorLinkList = ref([])
const anchorIndex = ref(0)
const sidebarMainRef = ref(null);
// 文章内容
const content = computed(() => {
const renderer = {
heading(text, level) {
// level代表几级标题 拼接上anchorIndex.value++ 放置id重复
const idName = level + '_' + anchorIndex.value++
const className = 'level' + level
anchorLinkList.value.push({
level: level,
title: text,
key: className,
href: '#' + idName
})
return `
<h${level} id=${idName} class=${className}>
${text}
</h${level}>
`
}
}
marked.use({ renderer })
marked.parse(detail.value.content)
})
const getContainer = () => {
return this.$refs.sidebarMain;
}
onMounted(() => {
sidebarMainRef.value = document.querySelector('.sidebar-main');
})
</script>
<template>
<div class="sidebar-main" ref="sidebarMainRef">
<div class="content" v-html="content"></div>
</div>
<a-anchor :getContainer="getContainer">
<a-anchor-link
v-for="link in anchorLinkList"
:key="link.key"
:href="link.href"
:class="link.key"
/>
</a-anchor>
<mtd-anchor class="title-wrap" :offset-top="20" container="#marked-content">
<mtd-anchor-link
v-for="link in anchorLinkList"
:href="link.href"
:title="link.title"
:key="link.key"
:class="link.key"
/>
</mtd-anchor>
</template>
<style scoped>
.level2 {
text-indent: 10px;
}
.level3 {
text-indent: 20px;
}
.level4 {
text-indent: 30px;
}
.level5 {
text-indent: 40px;
}
.level6 {
text-indent: 50px;
}
.title-wrap {
position: sticky;
top: 80px;
padding-right: 10px;
height: 400px;
overflow-y: auto;
}
#marked-content {
height: 100vh;
overflow-y: auto;
}
</style>
效果
规规矩矩的标题
不规矩的标题
ps
最开始想复杂了,就像写children那种嵌套的,但是 这种乱序的怎么写都不对
中午吃个饭 缓了缓,然后就想到了 写在同一级,然后拼上不同的class 来实现按照 间距的效果
然后就写出来了