Vue realizes the article directory

Table of contents is a very common function when we read articles. It not only helps us to quickly understand which points to introduce in this article, but also helps us quickly locate the title.

Let's take a look at my implementation method.

1. Set ref

<div v-html="xxx" ref="ff">
<!---内容区域--->
</div>

2. Obtain the subtitles in the article.

getTitle() {
      // 生成目录
      this.$nextTick(() => {
        // 根据之前设置的ref来获取文章的小标题
        const article_content = this.$refs.ff;//这里的ff改成你具体设置的
        // 想获取的标题,将想获取的小标题的标签添加到这
        const titleTag = ["H1", "H2", "H3"];
        //存放小标题的数组
        let titles = [];
        article_content.childNodes.forEach((e, index) => {
          //具体执行步骤,比如:打印看看
          console.log(e, index);
          if (titleTag.includes(e.nodeName)) {
            //具体封装过程
            console.log(e.nodeName);
            const id = "header-" + index;
            // 设置元素id
            e.setAttribute("id", id);
            titles.push({
              id: id,
              title: e.innerHTML,
              level: Number(e.nodeName.substring(1, 2)),
              nodeName: e.nodeName,
              //read:后期主要用来判断当前阅读的是哪一个小标题的内容
              read:false
            });
          }
        });
          //再data中定义catalog
        this.catalog = titles;
        console.log("23", this.catalog);
      });
    },

3. Display the article directory

<div class="colum">
   <h2>目录</h2>
    <ul class="catalog">
       <template v-for="(item, index) in catalog">
        <!---根据read属性(前面又说),动态绑定样式:为true即为正在阅读此内容--->
        <li
            :key="index"
            :style="{ paddingLeft: item.level * 30 - 44 + 'px'}"
            :class="{'cc':item.read == true}"
            >
          <!---设置href,用于目录的跳转;动态绑定id,判断当前正在阅读的是哪一个小标题的内容--->
          <a :href="'#' + item.id" :id="item.id">{
   
   { item.title }}</a>
       </li>
    </template>
  </ul>
</div>

<style>
.cc{
  background-color: rgb(254,242,235);
}
</style>

4. Determine which subtitle content is being read

Principle: Judging according to the distance between the subtitle and the top of the screen.

getReading(){
  //获取页面滚动值
  var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
  //遍历小标题
  for(let i=0;i<this.catalog.length;i++){
    //获取小标题距离屏幕顶端的距离
    var offsetTop = document.querySelector("#"+this.catalog[i].id).offsetTop;
      //根据条件做出判断,我这里是当小标题和屏幕顶端的距离小于300且没有被标明在读时,就将其背景颜色改变。
    if((offsetTop-scrollTop)<300&&(offsetTop-scrollTop)>0&&this.catalog[i].read==false){
      this.catalog[i].read = true
      //再将其他小标题背景色改成未读的背景色
      for(let j=0;j<this.catalog.length;j++){
        if(j!=i){
          this.catalog[j].read = false
        }
      }
    }
  }
}

Guess you like

Origin blog.csdn.net/m0_58991732/article/details/127720194