如何根据页面标签自动生成文章目录?分析+代码详解 | 您所在的位置:网站首页 › html的link标签怎么自动生成 › 如何根据页面标签自动生成文章目录?分析+代码详解 |
作者:Mintimate 博客:https://www.mintimate.cn Mintimate's Blog,只为与你分享 ![]() 文章目录功能大家再熟悉不过了吧,主要用于长篇文章、教程内:用户可以根据自己需求,点击目录进行跳转。 常见的目录效果: ![]() ![]() 这样的文章目录,难道要写到数据库里么? 当然不是 ,这个肯定是前端人员实现的。而且用简单的JavaScript就可以实现。 “Any application thatcanbe written in JavaScript,willeventually be written in JavaScript.” — — Jeff Atwood 问题分析一般需要生成目录的文章,标题都是需要标题和章节目录,所以必须要要有特定的标签修饰。举个例子,我这个网站是这样的: ![]() 按F12查看其源码: ![]() 分析源码: 网页应该是根据Markdown生成的文章分目录,使用html的标签,进行分层。每个标题标签,自带ID,可以使用“#”进行文章定位综上,就很清晰了: 提取内容部分的~标签(三层的目录……不多不少,嘿嘿),生成tree结构提取/放置标签ID,作为目录索引,便于目录功能的文章定位接下来,就叫大家分步操作。 封装标题标签封装标题标签的目的很简单,最终的效果: ![]() 为了实现这样的效果;首先,我们要在页面加载后,遍历文章: 如果你使用原生JavaScript,并没有使用任何框架,或者是JQ,那么就写在前即可。如果你使用的是Vue,那么写在method,或者mounted里调用都可以,最好加上this.$nextTick(()进行修饰,保证页面加载成功。遍历文章,很简单,我们使用childNodes方法和foreach循坏即可。 childNodes 属性返回节点的子节点集合,以 NodeList 对象。 实操演示如下。 遍历文章原生JavaScript单层包括,也就是需要生成目录的文章,外层有一个或其他双标签进行嵌套,如: ![]() 这个时候我们在根标签加上一个ID即可: ![]() 之后,在JavaScript内即可获取子元素: // 获取文章内容 const article_content = document.getElementById('content'); // 文章内容标签遍历 article_content.childNodes.forEach((e, index) => { //具体执行步骤,比如:打印看看 console.log(e) }![]() 这样就遍历成功了。 Vue实现这里在讲一下Vue如何实现,Vue不提倡我们直接操作页面DOM元素,所以这里我们可以在组件上加ref标签进行关联: ![]() 获取文章内容,就可以: // 根据ref获取内容 const article_content = this.$refs.markdownContent;但是,一般组件生成后,都是多标签进行包裹,要遍历文章标签,就需要children进行指定,比如: ![]() 所以,我们就可以这样遍历: article_content.children[0].children[0].childNodes.forEach((e, index) => { //具体执行步骤,比如:打印看看 console.log(e) }这样就遍历成功了。 ![]() 接下来,看到这些#text是不是束手无策?其实也很简单,我们进一步进行解析即可。 首先在循坏遍历的外侧,添加一个数组,如果页面元素标签,在这个数组范围内,就提取到标签集合并生成一个对象丢到titles内: // 哈哈,三级目录差不多了吧。云+社区也是三级目录~~~ const titleTag = ["H1", "H2", "H3"]; let titles = [];在遍历文章内容时,就可以判断标签是不是在数组内: if (titleTag.includes(e.nodeName)) { //具体封装过程 }之后,我们看看具体封装过程的逻辑实现。 首先是给文章每个标签,加上id,id的生成,我们使用变量时的index即可: const id = "header-" + index; // 设置元素id e.setAttribute("id", id);之后,就是把标签,解析成一个树,丢到titles内: titles.push({ id: id, title: e.innerHTML, level: Number(e.nodeName.substring(1, 2)), nodeName: e.nodeName });最终代码效果: < script type = "text/javascript" > const article_content = document.getElementById('content'); const titleTag = ["H1", "H2", "H3"]; let titles = []; article_content.childNodes.forEach((e, index) = >{ if (titleTag.includes(e.nodeName)) { const id = "header-" + index; e.setAttribute("id", id); titles.push({ id: id, title: e.innerHTML, level: Number(e.nodeName.substring(1, 2)), nodeName: e.nodeName }); } }); const catalog = titles; console.log(catalog); < /script>页面打印效果: ![]() 同时,Vue内也差不多: ![]() 最后,我们看看页面的渲染,页面渲染就可以根据喜好渲染了。比如我的(Vue工程): ![]() Vue工程可以使用v-for进行遍历,还是很简单的。 如果是原生JavaScript,就要自己拼接了…… // 原生JavaScript遍历 for (index in catalog) { document.getElementById('cataLog').innerHTML += "" + "" + catalog[index].title + """" };同时添加样式: .catalog{ position: sticky; }最终效果: ![]() ![]() 本次的前端分享就到这边~(真没想到,我一个学Linux和后端代码的“小学生”,有一天能讲前端代码实现……) ![]() 总的来说,生成目录还是很简单的。可能不是最优解,但是确实是个不错的方法。有什么问题,可以再评论留言嗷。 |
CopyRight 2018-2019 实验室设备网 版权所有 |