文章目录实现
内容标题绑定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
}
}