繁体   English   中英

添加 class 在滚动时处于活动状态。 香草JS

[英]Add class active on scroll. Vanilla JS

我是香草js的新手。 我有一个带有部分链接的导航栏。 我想在该部分激活后立即激活 class。 如果没有活动部分,则移除活动 class。 找到了这样一个脚本,但是有一个缺点。 如果我处于非活动部分,则活动 class 将保留在前一个活动部分。

 const links = document.querySelectorAll('.nav-link'); const sections = document.querySelectorAll('.forJS'); function changeLinkState() { let index = sections.length; while(--index && window.scrollY + 50 < sections[index].offsetTop) {} links.forEach((link) => link.classList.remove('active')); links[index].classList.add('active'); } changeLinkState(); window.addEventListener('scroll', changeLinkState);
 section{ height:100vh; scroll-y:auto; }.nav-link.active{ color: red; }
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"/> <body> <header class="fixed-top"> <nav class="navbar navbar-expand-lg navCustom"> <div class="container"> <ul class="navbar-nav justify-content-center"> <li class="nav-item"> <a class="nav-link" href="#main">Main</a> </li> <li class="nav-item"> <a class="nav-link" href="#about">About us</a> </li> <li class="nav-item"> <a class="nav-link" href="#portfolio">Portfolio</a> </li> <li class="nav-item"> <a class="nav-link" href="#contacts">Contacts</a> </li> </ul> </div> </nav> </header> <section class="forJS text-center">Some info 1</section> <section class="forJS text-center">Some info 2</section> <section class="forJS text-center">Some info 3</section> <section class="text-center">Some info 4</section> <section class="text-center">Some info 5</section> <section class="text-center">Some info 6</section> <section class="text-center">Some info 7</section> <section class="text-center">Some info 8</section> <section class="text-center">Some info 9</section> <section class="forJS text-center">Some info 10</section> </body>

PS看最后一行,有changeLinkState 它应该没有括号()吗? 而里面while是空的,为什么?

使用当前设计实现所需功能的最小更改是测试部分的高度以确保其可见,而不是像当前代码中那样无条件地将活动 class 添加到最近的导航链接。

if (window.scrollY - sections[index].offsetHeight < 
      sections[index].offsetTop) {
  links[index].classList.add('active');
}

代替:

links[index].classList.add('active');

您可以使用像scrollY + 50这样的偏移量来调整截止点,但在这里硬编码数字似乎并不理想。

完整代码:

 const links = document.querySelectorAll('.nav-link'); const sections = document.querySelectorAll('.forJS'); function changeLinkState() { let index = sections.length; while (--index && window.scrollY + 50 < sections[index].offsetTop) {} links.forEach((link) => link.classList.remove('active')); // add the active class if within visible height of the element if (scrollY - sections[index].offsetHeight < sections[index].offsetTop) { links[index].classList.add('active'); } } changeLinkState(); window.addEventListener('scroll', changeLinkState);
 section { height: 100vh; }.nav-link.active { color: red; } section { border: 1px solid #555; }
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" /> <body> <header class="fixed-top"> <nav class="navbar navbar-expand-lg navCustom"> <div class="container"> <ul class="navbar-nav justify-content-center"> <li class="nav-item"> <a class="nav-link" href="#main">Main</a> </li> <li class="nav-item"> <a class="nav-link" href="#about">About us</a> </li> <li class="nav-item"> <a class="nav-link" href="#portfolio">Portfolio</a> </li> <li class="nav-item"> <a class="nav-link" href="#contacts">Contacts</a> </li> </ul> </div> </nav> </header> <section class="forJS text-center">Some info 1</section> <section class="forJS text-center">Some info 2</section> <section class="forJS text-center">Some info 3</section> <section class="text-center">Some info 4</section> <section class="text-center">Some info 5</section> <section class="text-center">Some info 6</section> <section class="text-center">Some info 7</section> <section class="text-center">Some info 8</section> <section class="text-center">Some info 9</section> <section class="forJS text-center">Some info 10</section> </body>

您的其他问题已在评论中解决,但我将在这里重申答案:

  • changeLinkState上没有使用括号,因为我们将 function object 本身传递给稍后调用的回调。 如果我们像changeLinkState()那样调用它,我们最终会将undefined传递给回调并过早地触发处理程序,如此所述。
  • while是空的,因为它操纵终止条件(即--index )的块作为简写形式合并到条件中,如此所述。

除此之外,我将简要说明设计存在多个问题,并将其作为练习留给读者:

  • 引导布局将侧边栏 header 扩展到整个页面,因此 header 和元素之间可能存在无意的重叠。 如果 header 有背景,则内容将被遮挡。 我将重新审视这里的结构,以确保使用多个不重叠的列或流布局。
  • <section>标签应该在父容器中。
  • CSS 属性不应该是camelCased forJS不是特别明确的 class 名称。
  • scroll-y:auto; 是无效的 CSS 属性。 也许您的意思是overflow-y: auto; .
  • 触发滚动事件侦听器和迭代部分的策略有些原始。 查看throttling并考虑重构以使用Intersection Observer

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM