滚动重构时,香草JS会更改链接的活动状态

时间:2018-08-26 11:05:14

标签: javascript ecmascript-6

我正在尝试从即将进行的项目中放弃jQuery。我找到了一种使用纯Vanilla JS在滚动上创建粘性导航的方法,并希望导航中的链接在到达相应部分时更改其活动状态。

下面是我想出的有效解决方案,但是我确信可以改进代码以编程方式工作,而不必为每个元素选择和创建条件。

我还使用了许多不同的选择器,并且我很确定肯定有一种方法可以改进它,例如可以使用querySelectorAll并在{{1}中添加eventListener }循环,但我也无法使它正常工作。感谢您的帮助!

forEach
// select links
const allLinks = document.querySelectorAll('header nav ul li');
const linkTop = document.querySelector('#linkTop');
const linkAbout = document.querySelector('#linkAbout');
const linkServices = document.querySelector('#linkServices');
const linkClients = document.querySelector('#linkClients');
const linkContact = document.querySelector('#linkContact');
// select sections
const sectionTop = document.querySelector('#top');
const sectionAbout = document.querySelector('#about');
const sectionServices = document.querySelector('#services');
const sectionClients = document.querySelector('#clients');
const sectionContact = document.querySelector('#contact');

function changeLinkState() {
  // home
  if (window.scrollY >= sectionTop.offsetTop) {
    allLinks.forEach(link => {
      link.classList.remove('active');
    });
    linkTop.classList.add('active');
  }
  // about
  if (window.scrollY >= sectionAbout.offsetTop) {
    allLinks.forEach(link => {
      link.classList.remove('active');
    });
    linkAbout.classList.add('active');
  }
  // services
  if (window.scrollY >= sectionServices.offsetTop) {
    allLinks.forEach(link => {
      link.classList.remove('active');
    });
    linkServices.classList.add('active');
  }
  clients
  if (window.scrollY >= sectionClients.offsetTop) {
    allLinks.forEach(link => {
      link.classList.remove('active');
    });
    linkClients.classList.add('active');
  }
  contact
  if (window.scrollY >= sectionContact.offsetTop) {
    allLinks.forEach(link => {
      link.classList.remove('active');
    });
    linkContact.classList.add('active');
  }
}

window.addEventListener('scroll', changeLinkState);

非常感谢!

2 个答案:

答案 0 :(得分:0)

您可以使用document.querySelectorAll()获取所有部分和链接。滚动浏览时,从最后到第一部分遍历部分列表,直到找到匹配的部分。然后从所有链接中删除.active类,并将其添加到活动index处的链接中。

注意:您应该使用throttling来防止每秒changeLinkState多次调用。另一种选择是使用Intersection Observer API

const links = document.querySelectorAll('.links');
const sections = document.querySelectorAll('section');

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);
nav {
  position: fixed;
  top: 0;
  right: 0;
  width: 10em;
}

section {
  height: 100vh;
  margin: 1em 0;
  background: gold;
}

.active {
  background: silver;
}
<nav>
  <ul>
    <li id="linkTop" class="links">
      <a href="#top">Home</a>
    </li>
    <li id="linkAbout" class="links">
      <a href="#about">About Us</a>
    </li>
    <li id="linkServices" class="links">
      <a href="#services">Services</a>
    </li>
    <li id="linkClients" class="links">
      <a href="#clients">Clients</a>
    </li>
    <li id="linkContact" class="links">
      <a href="#contact">Contact</a>
    </li>
  </ul>
</nav>

<section>
  Home
</section>

<section>
  About Us
</section>

<section>
  Services
</section>

<section>
  Clients
</section>

<section>
  Contact
</section>

答案 1 :(得分:0)

突出显示Nav可以有多种方法。实现此功能的一种方法如下-

我们将“ active”类应用于活动的Nav链接,并为此类添加一些CSS以突出显示它。

以下是将“活动”类应用于正确的Nav链接的步骤:

STEP 1-

在创建导航栏时,为每个Nav链接添加一个与相应部分的ID相同的类。

例如,与具有id =“ section1”的部分相对应的Nav链接会将其类设置为section1(即class =“ section1”)

步骤2

在浏览器中的Scroll事件上,遍历每个部分并检查它是否在视口(getBoundingClientRect())中。

如果某部分位于视口中,则使它以及相应的Nav链接处于活动状态,如下所示-

if (section is in the viewport) {
    // 1. Add "your-active-class" to the current section
    // 2. Add "active" class to the Nav link which have a class same as id of the current section
    } else {
     // 1. Remove "your-active-class" from the current section.
 // 2. Remove "active" class from the Nav link which have a class same as id of current section
    }

步骤3

在css文件中,为“活动”和“活动类别”编写样式,以便可以使用不同的文本或背景颜色突出显示Nav链接和部分。