文章目录实现

内容标题绑定title-nav样式类

<div class="catalog-card">
          <div class="catalog-card-header">
              <div>
                  <span>目录</span>
              </div>
          </div>

          <div class="catalog-content">
              <div v-for="(item,index) in navList" @click="scrollToView(item)" :key="index" :class="['catalog-item',currentTitle == index ? 'active' : 'not-active',]">
                  {{ item.title }}
              </div>
          </div>
      </div>

css样式

.catalog-card {
    position: fixed;
    margin-top: 20px;
    background: white;
    border-radius: 8px;
    box-shadow: 0 3px 8px 6px rgba(7, 17, 27, 0.05);
    padding: 20px 24px;
    width: 160px;
    height: 475px;
    box-sizing: border-box;
}

.catalog-card-header {
    text-align: left !important;
    margin-bottom: 15px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.catalog-card-header div > span {
    font-size: 17px;
    color: #4c4948;
}
.catalog-content {
    max-height: calc(100vh - 120px);
    overflow: auto;
    margin-right: -24px;
    padding-right: 20px;
}
.catalog-item {
    color: #666261;
    margin: 5px 0;
    line-height: 28px;
    cursor: pointer;
    transition: all 0.2s ease-in-out;
    font-size: 14px;
    padding: 2px 6px;
    display: -webkit-box;
    overflow: hidden;
    text-overflow: ellipsis;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;

    &:hover {
        color: #1892ff;
    }
}
.active {
    color: white;
    background-color: #3e8bff;
    &:hover {
        background-color: #0c82e9;
        color: white;
    }
}

防抖

function debounce(fn,delay){
    let timer
    return (...args)=>{
      clearTimeout(timer)
      timer=setTimeout(()=>fn(...args),delay)
    }
  }

js目录标题获取,目录选中控制

const elements = document.querySelectorAll(".title-nav");
const titles=[]
for (let i = 0; i < elements.length; i++) {
  const element = elements[i];
  let node={
    id:i,
    title:element.innerText,
    element: element,
  }
  titles.push(node)
}
//目录标题获取
this.navList=titles
window.addEventListener("scroll",debounce(this.scrollHander,200))
scrollToView(item) {
    this.currentTitle=item.id
    item.element.scrollIntoView({ behavior: "smooth" })
},
scrollHander(){
    if(this.navList[0].element.getBoundingClientRect().top>300){
        this.currentTitle=0
        return
    }
    for(let i=0,len= this.navList.length;i<len;i++){
      let top=this.navList[i].element.getBoundingClientRect().top
      // 切换区域顶部300px
      if(top>=0&&top<=300){
        this.currentTitle=this.navList[i].id
        break
      }
      // 视图第一标题300px外
      else if(top<0&&this.navList[i+1]&&this.navList[i+1].element.getBoundingClientRect().top>300){
        this.currentTitle=this.navList[i].id
        break
      }
}

posted @ 2023-12-25 10:27  年轻浅识  阅读(2)  评论(0编辑  收藏  举报