【问题标题】:Could anyone literally translate this JavaScript function in an easy-to-understand way?谁能以一种易于理解的方式逐字翻译这个 JavaScript 函数?
【发布时间】:2019-07-05 13:59:51
【问题描述】:

https://codepen.io/zchee/pen/ogzvZZ

上面的 codepen 链接包含一个滚动动画示例,当您向下滚动时,它会改变导航的行为和外观,这是使用纯原生 JavaScript 完成的。问题是我不明白这个脚本是如何工作的。我对 JavaScript 有基本的了解,到目前为止我知道...

  1. 有 3 个变量——section(选择“section”类)、一个空对象 {},以及在函数内部的值为 0 的 i。

  2. 研究了一下,发现Array.prototype.forEach.call[ ].forEach(function())是一样的。所以据我了解, e 是一个参数。从这里开始,我迷路了,因为我不知道这意味着什么 section[e.id] = e.offsetTop;

  3. 好的,所以我理解 window.onscroll = function() {} 但不是 100% 确定为什么我们需要为 scrollPosition 创建一个等于 scrollTop 或 body.scrollTop 的变量?

我对其余的代码感到迷茫……我很欣赏逐行解释。谢谢。

(function() {
  'use strict';

  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');
      }
    }
  };
})();

【问题讨论】:

  • 创建scrollPosition 变量不是必要,但它允许稍后在short if 语句中使用它(它如果是if (sections[i] &lt;= (document.documentElement.scrollTop || document.body.scrollTop)) {,看起来会更糟

标签: javascript html foreach


【解决方案1】:

所以如果你看一下这个函数,你会发现它是一个Immediately Invoked Function Expression (IIFE),这意味着它是一个一旦遇到就会执行的函数。当函数运行时,它会执行以下操作:

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

这会找到所有具有section 类的节点。这将返回一个NodeList。这将代表&lt;div id="home" class="section"&gt;&lt;/div&gt; 等。

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

这是一种遍历具有像数组这样的属性的列表的方法。如果它是一个数组,则将直接在其上调用 forEach(根据下面的@RobG)。这会将每个sectionid 属性存储到sections 对象中,该对象用作带有偏移顶部值的查找,即渲染时每个部分离顶部有多远。

window.onscroll = function() {}

每次滚动都会触发的事件处理程序。

var scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;

到目前为止,您从顶部滚动了多远。

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

这会遍历所有部分,并检查您是否至少从文档顶部向下滚动了该部分的内容。如果你有,然后找到当前活动的部分并删除它的类,它不再是活动的。然后找到a标签,它代表与该部分相关的菜单链接,然后将其类设置为活动。

【讨论】:

  • 非常感谢!现在我对它有了更好的理解。我会逐渐接受你的解释,并使用我自己的类似方法进行更多练习。
  • "find the current active section" 实际上是“find the first element with an active class”,这是一个实际的流程代码,确实会更好地找到当前活动的部分,就像代码没有检查
    是否真的有一个 id 并且真的应该映射到它们的锚点,也没有使用严格的属性检查对于锚点,所以如果它们有部分domainmaintenancemain,它将中断。
【解决方案2】:

既然其他人已经给你解释过了,我就试着重写它以使其更具可读性?

{
  let sectionNodes = document.getElementsByClassName("section"),
      sectionTopPositions = {}
      
  for (let node of sectionNodes) {
    sectionTopPositions[node.id] = node.offsetTop
  }
  
  function onWindowScroll() {
    let scrollPosition = document.documentElement.scrollTop
      || document.body.scrollTop
    
    for (let [nid, topPos] of sectionTopPositions) {
      if (topPos <= scrollPosition) {
        let activeNodes = document.getElementsByClassName("active"),
            linkNodes = document.querySelector(`a[href*=${nid}]`)
        
        activeNodes.className = ""
        linkNodes.className = "active"
      }
    }
  }
  
  window.addEventListener("scroll", onWindowScroll)
}

【讨论】:

    猜你喜欢
    • 2015-06-02
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多