简单的生成文章内容目录(vue可用)
t-jian 时间:2022-03-04
在富文本辑编器里面写文章时,我们通常会使用h1-h6标签来定义章节标题。在用户端显示时希望展示目录结构。如图;
这里生成目录结构可以借助第三方插件来实现,但某些情况下不希望引用太多的第三方资源就需要自己实现一个。
核心思路:拿到所有的h标签的节点集合,这个集合就是内容(平级)的目录,我们只需要将平级目录根据标签的(level 等级)/大小,设定一个缩进的长度乘标签大小就可生成有层次的目录结果。为了能使用使用瞄点定位,故每个节点设定一个id
核心处理代码
//拿到文章内容的节点 let parent = document.getElementById("previewer") //拿到文章里面的h1-h6标签 let doms = parent.querySelectorAll('h1,h2,h3,h4,h5,h6'); let hEles = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] //结果集 let catalogue = []; let index = 0; if(doms.length>0){ doms.forEach(element => { var nodetext = element.innerHTML.replace(/<\/?[^>]+>/g, ""); nodetext = nodetext ); let name = element.nodeName.toLowerCase(); if (hEles.includes(name)) { index++; let id = `catalogue_${index}`; //为当前节点添加id,方便使用瞄点定位 element.setAttribute("id", id) let level = name.replace("h", ""); catalogue.push({ id: id, key: name, title: nodetext, level: Number(level) }); } });
以下是vue版本的实现
let data = reactive({ news: {}, loading: true, catalogue: [] }) const { proxy } = getCurrentInstance() let id = proxy.$root.$router.currentRoute.value.params.id onMounted(() => { proxy.$http.get(`/api/blog/news/${id}`).then((res) => { data.news = res; document.title = res.title; }); }) nextTick(() => { setTimeout(() => { //等待dom 加载完成 uParse("#previewer", { rootPath: 'https://cdn.jsdelivr.net/gh/t-jian/static/theme/ueditor-1.4.3/', liiconpath: 'https://cdn.jsdelivr.net/gh/t-jian/static/theme/ueditor-1.4.3/listicon/', }); setTimeout(() => { //防止闪烁 data.loading = false; //目录导航 let parent = document.getElementById("previewer") let doms = parent.querySelectorAll('h1,h2,h3,h4,h5,h6'); let hEles = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] let catalogue = []; let index = 0; if(doms.length>0){ doms.forEach(element => { var nodetext = element.innerHTML.replace(/<\/?[^>]+>/g, ""); nodetext = nodetext.replace(/ /ig, ""); let name = element.nodeName.toLowerCase(); if (hEles.includes(name)) { index++; let id = `catalogue_${index}`; element.setAttribute("id", id) let level = name.replace("h", ""); catalogue.push({ id: id, key: name, title: nodetext, level: Number(level) }); } }); data.catalogue = catalogue; } }, 100); }, 300);
<div class="item-card rt-panel"> <div class="nav-title">文章导航</div> <ul class="catalogue-box"> <li v-for="item in catalogue" :key="item"> <a :href="'#'+item.id"><span :style="'margin-left:'+(4*item.level)+'px;'">{{item.title}}</span> </a> </li> </ul> </div>
特别声明:本站部分内容收集于互联网是出于更直观传递信息的目的。该内容版权归原作者所有,并不代表本站赞同其观点和对其真实性负责。如该内容涉及任何第三方合法权利,请及时与824310991@qq.com联系,我们会及时反馈并处理完毕。