为你的博客添加目录索引

xxxsimons

一、前言

演示图例

GIF.gif

需求

这个目录索引应该包含以下功能:

  • 点击目录项跳转到对应锚点
  • 屏幕滚动时,对应目录项样式变化

话不多说,开始干!

二、点击目录项跳转到对应锚点

hash模式的路由下的锚点

说到文章的目录索引,首先想到的就是锚点了。然而在hash模式的路由下,如果使用原始的锚点方案会造成下面这样的问题。

// 文章url链接,hash模式下
www.rychou.xyz/#/article/70 

// 如果采用传统的锚点方式,比如有个锚点:anchor-1,点击之后,url会变成

www.rychou.xyz/#anchor-1

很明显,在hash模式下,就不能采用这种方式锚点了。我采用了自定义锚点的方式。

参考:vue2.0中怎么做锚点定位

添加锚点和初始化目录的数据结构

方法有了,然后就是怎么给文章加添加锚点了。

我采用了遍历dom树,然后找到文章的h1标签(暂时只对h1标签建立索引),为其添加id的方式建立索引。

// 初始化文章锚点和目录数据结构
getDirectories() {
      let directories = document.querySelectorAll(".article-content h1"); //找到属于文章内容的h1标签
      directories.forEach((element, index) => {
        element.id = "anchor-" + index;//添加id
        this.directories.push({
          title: element.innerText, //h1标签文本内容
          offsetTop: element.offsetTop, //记录当前h1标签的偏移量,方便后面计算滚动距离。
          isActive: false //是否被选中
        });
      });

实现点击跳转到对应锚点

<div v-for="(item,index) in directories" :key="index">
   <a href="javascript:void(0)" @click="goAnchor(index)" >
     {{item.title}}
   </a>
</div>


methods:{
  goAnchor(index) {
      document.documentElement.scrollTop = this.directories[index].offsetTop;
    },
}

三、屏幕滚动时,对应目录项样式变化

注意我们前面初始化目录数据结构中,包含了一个叫isActive的状态位,就是根据这个状态位来进行相应的渲染

动态绑定class

<div class="directories-container">
    <div class="directories-list">
      <h2>目录</h2>
      <div :class="{'highlight-title':item.isActive}" v-for="(item,index) in directories" :key="index" style="padding: 5px 12px;">
        <a href="javascript:void(0)" @click="goAnchor(index)" >
          {{item.title}}
        </a>
      </div>
    </div>
</div>

添加滚动监听

// 挂载页面时,添加滚动监听
mounted() {
    window.addEventListener("scroll", this.handleScroll);
  },
// 退出页面时,应该取消监听
destroyed() {
    window.removeEventListener("scroll", this.handleScroll);
},

计算状态位isActive

handleScroll(e) {
      let scrollTop = document.documentElement.scrollTop //当前滚动距离
      this.directories.forEach((element,index)=>{
        if((scrollTop)>=element.offsetTop){//当前滚动距离大于某一目录项时。
          for(let i=0;i<index;i++){
            this.directories[i].isActive = false //同一时刻,只能有一个目录项的状态位为Active,即此时其他目录项的isActive = false
          }
          element.isActive = true; //将对应的目录项状态位置为true
        }else{
          element.isActive = false;
        }
      })
}

css样式

// scss
.directories-container {
  width: 15vw;
  transition: all 0.5s;
  margin-left: 10px;
  .highlight-title {
    border-left: 3px solid rgb(15, 105, 223);
    background-color: rgb(243, 243, 243);
    z-index: -1;
    a{
      color: rgb(15, 105, 223)
    }
  }
  .directories-list {
    position: -webkit-sticky;
    position: sticky; 
    top: 0;
    word-wrap: break-word;
    background-color: #fff;
    border-left: 1px solid rgb(236, 236, 236);
    z-index: 999;
    a {
      &:hover {
        text-decoration: underline;
      }
    }
  }
}
原文链接: 为你的博客添加目录索引

欢迎关注公众号:开源学院
图片描述

阅读 1.8k

大四前端一枚

591 声望
29 粉丝
0 条评论
你知道吗?

大四前端一枚

591 声望
29 粉丝
宣传栏