简体   繁体   English

对突出显示滚动中的活动菜单项感到困惑(Vanilla JS)

[英]Confused about highlighting active menu item on scroll (Vanilla JS)

I found this function which highlights the active menu anchors when you scroll to sections that have the same id. 我发现此功能可在您滚动到具有相同ID的部分时突出显示活动菜单锚。 I understand how most of the code works, but I don't get how the window onscroll event knows how to update the right anchor tag with the .active class. 我了解大多数代码的工作原理,但我不了解window onscroll事件如何知道如何使用.active类更新正确的定位标记。

All the JS: 所有的JS:

  var section = document.querySelectorAll(".section"); var sections = {}; var i = 0; Array.prototype.forEach.call(section, function(e) { sections[e.id] = e.offsetTop; }); window.onscroll = function() { var scrollPosition = document.documentElement.scrollTop || document.body.scrollTop; for (i in sections) { if (sections[i] <= scrollPosition) { document.querySelector('.active').setAttribute('class', ' '); document.querySelector('a[href*=' + i + ']').setAttribute('class', 'active'); } } }; 

From this Pen: https://codepen.io/zchee/pen/ogzvZZ 从这支笔: https : //codepen.io/zchee/pen/ogzvZZ

This part confuses me: 这部分使我感到困惑:

document.querySelector('a[href*=' + i + ']').setAttribute('class', 'active');

I get that setAttribute adds a class of active to the anchor tag — but how does querySelector find the right anchor to update when you scroll? 我知道setAttribute将一个活动类添加到锚标记中-但是当滚动时querySelector如何找到正确的锚来更新?

I tried logging the index variable [i] from the (for in array loop) to get the id of the current section (onscroll) but it returns the current scroll position (as a number). 我尝试从(在数组循环中)记录索引变量[i]以获取当前节的ID(滚动),但它返回当前滚动位置(以数字表示)。

This is why I don't get why the inserted 'i' variable here: ('a[href*=' + i + ']') represents the corresponding section id in the onscroll event. 这就是为什么我不明白为什么此处插入的'i'变量:( ('a[href*=' + i + ']')代表onscroll事件中相应的段ID的原因。

I guess it doesn't help that I don't really understand how this forEach function operates: 我想我不太了解此forEach函数的运行方式没有帮助:

Array.prototype.forEach.call(section, function(e) {
sections[e.id] = e.offsetTop;
});

I get that it loops through all sections and pushes the sections[e.id] to the empty object sections = {} which is used later in the onscroll event — but that's where my understanding stops. 我知道它循环遍历所有部分,并将这些sections[e.id]推送到空对象sections = {} ,稍后将在onscroll事件中使用它,但是我的理解在那里停止了。 :-/ :-/

I'm sorry I don't know how to phrase this question better. 对不起,我不知道如何更好地表达这个问题。 I've spent hours trying to wrap my head around it. 我已经花了几个小时试图绕过它。 I can't find any topic examples that are similar to this, but I want to understand how it works before I use it anywhere. 我找不到任何与此类似的主题示例,但是我想在任何地方使用它之前先了解其工作原理。

Would greatly appreciate some feedback! 非常感谢您的反馈! :-) :-)

According to documentation from W3 schools, .querySelector gets the first element in the document with class equalling the one being searched for. 根据W3学校的文档.querySelector获取文档中的第一个元素,其类等于要搜索的元素。

a[href*=#] means the querySelector is looking for all elements containing a # , and in your case 'a[href*=' + i + ']' is further specifying elements that has the current href of i . a[href*=#]表示querySelector正在查找包含#所有元素,在您的情况下, 'a[href*=' + i + ']'进一步指定当前hrefi元素。

So when you piece everything together, the code 因此,当您将所有内容组合在一起时,代码

for (i in sections) {
  if (sections[i] <= scrollPosition) {
    document.querySelector('.active').setAttribute('class', ' ');
    document.querySelector('a[href*=' + i + ']').setAttribute('class', 'active');
  }
}

looks for the element with an href equalling the current 'i' section, and sets the attribute class to active for that element. 查找具有等于当前“ i”部分的href的元素,并将该元素的属性类设置为active。

Hope it helps! 希望能帮助到你!

EDIT 编辑

Whenever the window is scrolled, the following happens: 每当滚动窗口时,都会发生以下情况:

  1. 1) A variable is set called scrollPosition , which is set equal to the documentElement's "highest" point (or scrollTop) OR the document body's "highest" point (or scrollTop) 1)设置一个名为scrollPosition变量,该变量设置为等于documentElement的“最高”点(或scrollTop) 文档正文的“最高”点(或scrollTop)
  2. Then, for i in all sections: if the section is less than or equal to the scrollPostition, it changes the previously active class to null and sets the current section's class to active. 然后,对于所有节中的i :如果该节小于或等于scrollPostition,则它将先前处于活动状态的类更改为null并将当前节的类设置为活动。

It then repeats for each section, until it arrives at the current section. 然后,对每个部分重复此操作,直到到达当前部分。 So technically, every section is up to the current section is made "active" at some point (hence the console logs of each section name). 因此,从技术上讲,直到当前节为止的每个节在某个时候都处于“活动”状态(因此,每个节名称的控制台日志)。

Essentially, if you were to go from "Home" to "Contact", it would remove the active class from "Home" and add it to "Portfolio", then remove it from "Portfolio" and add it to "About", before finally removing it from "About" and adding it to "Contact". 本质上,如果要从“主页”转到“联系”,它将在“主页”中删除活动类并将其添加到“ Portfolio”,然后将其从“ Portfolio”删除并将其添加到“关于”,然后最后将其从“关于”中删除,并将其添加到“联系人”中。 That way it appears to 'know' what section you're on, but it's actually going through all of them until it reaches the right one. 这样,它似乎可以“知道”您正在执行的部分,但实际上是遍历所有部分,直到到达正确的部分为止。

(Another example: If you went from "Contact" to "Portfolio", it would remove active from "Contact" and add it to "Home", realize it's still not on the right one, then remove active from "Home" and add it to "Portfolio". This probably wouldn't work as well for a site with a bunch of sections, but it appears seamless on smaller/mid-size websites!) (另一个示例:如果您从“联系人”转到“投资组合”,则会从“联系人”中删除活动内容并将其添加到“首页”,意识到它仍不在正确的位置,然后从“首页”中删除活动内容并添加将其添加到“投资组合”中。这对于具有多个部分的网站可能无法正常工作,但在中小型网站上似乎是无缝的!)

There might be better ways to explain this, but I hope this 'visual' helps! 也许有更好的方法来解释这一点,但我希望这种“视觉”有所帮助!

Its very simple. 非常简单。 Your variable section contains all divs with class ".section" as you see the code 您看到的代码中,变量部分包含所有带有类“ .section”的div。

var section = document.querySelectorAll(".section");

Then your "sections" array is filled with all div ids and their scroll positions according to window offset value by using the code 然后,使用代码根据窗口偏移值,将所有div ID及其滚动位置填充到“ sections”数组中


    Array.prototype.forEach.call(section, function(e) {
    sections[e.id] = e.offsetTop;
    });
    

Your sections array will be like this in memory 您的section数组在内存中将像这样


    sections['home']=position of home 
    sections['portfolio']=position of portfolio
    sections['about']=position of about
    sections['contact']=position of contact
    

So when for loop works on sections, it gives the div id like this 因此,当for循环在部分上运行时,它会像这样给出div id

for (i in sections) {
    * now "i" gives the id of all div one by one
    }

Meanwhile in this loop querySelector will search anchor tag which contains specific href text 同时,在此循环中,querySelector将搜索包含特定href文本的锚标记。

*this will give you specific anchor tag like
    *document.querySelector('a[href*='home']')
    -> a[href*='home']
    -> a[href*='portfolio']
    -> a[href*='about']
    -> a[href*='contact']

I hope this will explain you easily. 我希望这可以轻松地向您解释。

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

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