文章大纲

如何在博客文章右边加上文章目录索引

2020-09-06 10:57:19

为了让自己的博客文章有更好的阅读体验,昨晚翟码农给博客文章添加了目录导引。



现主要记录下其思想,本文代码为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的容差。

注意:判断位置是否到达,由于一些不明原因,需要加入一定像素的容差


所有代码

以下是翟码农实现给文章添加目录的所有代码,大家能用得上就用吧。
html部分:
<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”错误。


我要评论
评论列表