我正在尝试从即将进行的项目中放弃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);
非常感谢!
答案 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链接和部分。