为了让自己的博客文章有更好的阅读体验,昨晚翟码农给博客文章添加了目录导引。
现主要记录下其思想,本文代码为jQuery框架下的,使用vue框架的,或者给博客园、wordpress博客文章添加目录的,原理都相似,对代码稍稍调整即可。
要实现文章目录索引效果,主要实现以下3个任务:
1.假定博客里标题固定为h3、h4格式,先将这些标题内容获取出来,生成目录。
2.点击目录链接,文章滚动到指定位置。
3.滚动文章,对应目录的链接样式能高亮显示
如果想直接看全部代码的,就直接拉到文章末尾。实现效果,尝试点击本文章里目录或者滚滚文章试试吧。
用jQuery实现也很简单,用如下一行代码就可以获取文章里所有用h3和h4格式的标题。
let titles = document.querySelectorAll(".box-content h3,h4");
.box-content是翟码农博客文章div的class,大家根据自己实际情况修改即可。
在文章页面添加好如下div,用来展示目录:
<div class="box-directory"> <div class="top-title">文章大纲</div> </div>
再遍历上面获取的标题,将其塞进上面目录div里。
titles.forEach((element, index) => { var linkItem = document.createElement('a'); linkItem.innerHTML = element.innerHTML; linkItem.setAttribute('id', 'anchor_'+index); linkItem.setAttribute('class', 'link-index'); linkItem.href = 'javascript:void(0)'; indexBoxItem.append(linkItem); });
生成目录步骤里,生成的目录会如下:
<div class="box-directory"> <div class="top-title">文章大纲</div> <a id="anchor_0" class="link-index" href="javascript:void(0)">1.安装Nginx</a> <a id="anchor_1" class="link-index" href="javascript:void(0)">2. 安装php-fpm</a> <a id="anchor_2" class="link-index" href="javascript:void(0)">3.安装mysql数据库</a> <a id="anchor_3" class="link-index" href="javascript:void(0)">4. 安装redis</a> </div>
但是这样,点击目录链接,我们并不知道要将文章滚动到哪里。
所以在前面遍历文章标题时,我同时将标题的位置offsetTop给存储在目录超链接里了。
linkItem.setAttribute('offset_top', element.offsetTop);
得到的目录html就变成如下:
<a id="anchor_0" class="link-index" offset_top="926" href="javascript:void(0)">1.安装Nginx</a>
这样实现之后,给超链接加个点击事件,跳到offsetTop指定位置就好了。
$(document).on("click", ".box-directory a", function(){ var item = this; $(document).scrollTop(item.getAttribute('offset_top')); });
这个算是美化效果吧,就是在滚动文章时,判断到达哪个目录的内容了,就将对应的目录高亮显示。
这个工作,我是通过先移除所有超链接active这个class、再给需要高亮的目录添加active这个class来实现的(active这个class的css样式要自己写的)。
$(window).scroll(function(){ var now_scroll = $(window).scrollTop(); console.log('now scroll'+now_scroll); let titles = document.querySelectorAll(".box-content h3,h4"); titles.forEach((element, index) => { if(now_scroll >= element.offsetTop - 10){ $(".article-index-box a").removeClass("active"); $("#anchor_"+index).addClass("active"); } }); });
这里不知为何,目录超链接里offsetTop为4038,但点击目录后,文章跳到指定了位置,但上面代码now_scroll的值却是4037.6,所以上面判断位置是否到达:now_scroll >= element.offsetTop,翟码农加入了10px的容差。
注意:判断位置是否到达,由于一些不明原因,需要加入一定像素的容差
<div class="box-directory"> <div class="top-title">文章大纲</div> </div>
js部分(需要jquery.js支持):
<script type="text/javascript"> function getBlogIndex(){ var indexBoxItem = $(".box-directory"); let titles = document.querySelectorAll(".box-content h3,h4"); titles.forEach((element, index) => { element.id = "coderzhai_anchor_"+index; var linkItem = document.createElement('a'); linkItem.innerHTML = element.innerHTML; linkItem.setAttribute('id', 'anchor_'+index); linkItem.setAttribute('class', 'link-index'); linkItem.setAttribute('offset_top', element.offsetTop); linkItem.href = 'javascript:void(0)'; indexBoxItem.append(linkItem); }); } $(document).on("click", ".box-directory a", function(){ var item = this; $(".article-index-box a").removeClass("active"); $(item).addClass("active"); $(document).scrollTop(item.getAttribute('offset_top')); }); $(window).scroll(function(){ var now_scroll = $(window).scrollTop(); let titles = document.querySelectorAll(".box-content h3,h4"); titles.forEach((element, index) => { if(now_scroll >= element.offsetTop - 10){ $(".article-index-box a").removeClass("active"); $("#anchor_"+index).addClass("active"); } }); }); </script>
css部分:
.box-directory{ position: fixed; top: 100px; right: 0px; left: 50%; margin-left: 400px; } .box-directory .top-title{ font-size:18px; margin-bottom:10px; width: 80px; border-bottom: 1px solid white; padding-bottom: 5px; } .box-directory a{ display:block; padding: 5px 0px; color:#999; } .box-directory a.active{ color:orange; }
本文为翟码农个人博客里前端综合分类下的技术原创文章,转载请注明出处:http://www.zhai14.com/blog/how-to-add-index-corresponding-to-the-article-on-the-right-side.html
有一段时间没写jquery js代码了,关于一些小知识点,中间百度了不少,现记录如下:
1.获取所有节点,用document.querySelectorAll
2.html标签自带的属性,可以直接赋值,否则就要用getAttribute,setAttribute
3.js forEach语法
elements.forEach((element, index) => { //to do sth });
4.根据class元素的click事件方法里,this要带上$,如$(this)这样,才能使用节点方法。
本次实践,由于疏忽了这点,代码一直报“addclass is not a function”错误。