繁体   English   中英

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

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

我发现此功能可在您滚动到具有相同ID的部分时突出显示活动菜单锚。 我了解大多数代码的工作原理,但我不了解window onscroll事件如何知道如何使用.active类更新正确的定位标记。

所有的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'); } } }; 

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

这部分使我感到困惑:

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

我知道setAttribute将一个活动类添加到锚标记中-但是当滚动时querySelector如何找到正确的锚来更新?

我尝试从(在数组循环中)记录索引变量[i]以获取当前节的ID(滚动),但它返回当前滚动位置(以数字表示)。

这就是为什么我不明白为什么此处插入的'i'变量:( ('a[href*=' + i + ']')代表onscroll事件中相应的段ID的原因。

我想我不太了解此forEach函数的运行方式没有帮助:

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

我知道它循环遍历所有部分,并将这些sections[e.id]推送到空对象sections = {} ,稍后将在onscroll事件中使用它,但是我的理解在那里停止了。 :-/

对不起,我不知道如何更好地表达这个问题。 我已经花了几个小时试图绕过它。 我找不到任何与此类似的主题示例,但是我想在任何地方使用它之前先了解其工作原理。

非常感谢您的反馈! :-)

根据W3学校的文档.querySelector获取文档中的第一个元素,其类等于要搜索的元素。

a[href*=#]表示querySelector正在查找包含#所有元素,在您的情况下, 'a[href*=' + i + ']'进一步指定当前hrefi元素。

因此,当您将所有内容组合在一起时,代码

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

查找具有等于当前“ i”部分的href的元素,并将该元素的属性类设置为active。

希望能帮助到你!

编辑

每当滚动窗口时,都会发生以下情况:

  1. 1)设置一个名为scrollPosition变量,该变量设置为等于documentElement的“最高”点(或scrollTop) 文档正文的“最高”点(或scrollTop)
  2. 然后,对于所有节中的i :如果该节小于或等于scrollPostition,则它将先前处于活动状态的类更改为null并将当前节的类设置为活动。

然后,对每个部分重复此操作,直到到达当前部分。 因此,从技术上讲,直到当前节为止的每个节在某个时候都处于“活动”状态(因此,每个节名称的控制台日志)。

本质上,如果要从“主页”转到“联系”,它将在“主页”中删除活动类并将其添加到“ Portfolio”,然后将其从“ Portfolio”删除并将其添加到“关于”,然后最后将其从“关于”中删除,并将其添加到“联系人”中。 这样,它似乎可以“知道”您正在执行的部分,但实际上是遍历所有部分,直到到达正确的部分为止。

(另一个示例:如果您从“联系人”转到“投资组合”,则会从“联系人”中删除活动内容并将其添加到“首页”,意识到它仍不在正确的位置,然后从“首页”中删除活动内容并添加将其添加到“投资组合”中。这对于具有多个部分的网站可能无法正常工作,但在中小型网站上似乎是无缝的!)

也许有更好的方法来解释这一点,但我希望这种“视觉”有所帮助!

非常简单。 您看到的代码中,变量部分包含所有带有类“ .section”的div。

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

然后,使用代码根据窗口偏移值,将所有div ID及其滚动位置填充到“ sections”数组中


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

您的section数组在内存中将像这样


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

因此,当for循环在部分上运行时,它会像这样给出div id

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

同时,在此循环中,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']

我希望这可以轻松地向您解释。

暂无
暂无

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

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