看到这个需求,第一感觉肯定是装插件,因为Markdown文章其实是自带目录的,只要在文章中加一句@TOC,目录就会自己生成,但是如果文章本来就有目录,再获取一遍放旁边,显然要实现的并非这个效果,我们要做的是把文章中的标题获取出来,然后拼接成一个目录,最终效果如下图所示:
1、首先,先给文章加上一个id,方便后边获取到他。
<div class="nimbus-editor-styl" id="contents" v-html="detail.content"></div>
2、给需要添加目录的地方放一个盒子
<div v-if="tocShow" id="toc"></div>
3、最重要的当然是获取标题,拼接目录
var toc = "";
var level = 0;
if(document.querySelector('#contents')){
var container = document.querySelector('#contents');
var output = '#toc';
let atitle = document.querySelectorAll('a')
if(atitle){
for(var i = 0;i < atitle.length;i++){
atitle[i].style = 'padding-top: 64px;margin-top: -64px;'
}
}
container.innerHTML.replace(/<h([\d])>(.*?)<\/h([\d])>/g, //这一步是匹配到文章内容中的h1-h6标签
function (str, openLevel, titleText, closeLevel) {
if (openLevel != closeLevel) {
return str;
}
if (openLevel > level) { //下一个比前一个小就一层,大就和上一场同级
toc += (new Array(openLevel - level + 1)).join('<ul>');
} else if (openLevel < level) {
toc += (new Array(level - openLevel + 1)).join('</li></ul>');
} else {
toc += (new Array(level+ 1)).join('</li>');
}
level = parseInt(openLevel);
if(titleText.match(/<a(.*?)<\/a>/g)){ //匹配标题中的a标签
let str1 = titleText.match(/<a(.*?)<\/a>/g)[0]
let aid = str1.match(/id="(.*?)"/g)[0] //匹配a标签中的id,并将id获取出来
aid = aid.replace('id="', "").replace('"',"")
titleText = titleText.replace(/<a(.*?)<\/a>/g, "")
titleText = `<a href="#${aid}" class="font12 nowrap titleText">${titleText}</a></div>`
toc += '<li><div class="flex mb4"><i class="nb-pull-down"></i>' + titleText;
}
});
if (level) {
toc += (new Array(level + 1)).join('</ul>');
}
if(toc.match(/<ul><ul>/g)){ //因为匹配时发现结果中出现多个空的ul标签,这里替换掉空的
toc = toc.replace(/<ul><ul><ul>+/g,'<ul>').replace(/<\/ul><\/ul> <\/ul>+/g,'</ul>')
}
document.querySelector(output).innerHTML = ''
document.querySelector(output).innerHTML += toc;
let liArr = document.querySelectorAll('li') //因为拼接好的目录只有margin来决定层级,所有决定给他增加一个icon,此时需要判断,如果li没有下一层,就不加icon,如果有下一层,则加上icon
if(liArr){
for(var i = 0;i < liArr.length;i++){
if(liArr[i].innerHTML.match('<ul>')){
}else{
liArr[i].innerHTML = liArr[i].innerHTML.replace('<i class="nb-pull-down"></i>','').replace('font12 nowrap titleText','font12 nowrap titleText ml16')
}
}
}
}else{
return
}