【问题标题】:Understanding "hide nav-bar on scroll" code - Javascript了解“滚动时隐藏导航栏”代码 - Javascript
【发布时间】:2020-09-07 11:06:28
【问题描述】:

我正在学习 JS,我有一个测试页面,我可以在其中练习我的新“发现”。

我在 Youtube (Here the link if somebody's interested) 上关注了如何根据滚动事件隐藏/显示导航栏的教程。我将它应用到我的测试页面,当然它运行良好,正如您从 sn-p 中看到的那样,但我在理解 2 个特定点时遇到了一些麻烦。希望有人可以用“可怜”的词来解释它们。

所以,这里是 滚动事件的 JS 代码

const header = document.querySelector('header');
let prev = window.pageYOffset;

window.addEventListener('scroll', function(){
  let current = window.pageYOffset;
  if(prev < current){
    header.classList.add('hide');
  }
  else {
    header.classList.remove('hide');
    }

    prev = current;

})

点 n°1

  • IF 语句 中,如果没有赋值,let prev; 如何知道小于let current;?我试着把它想象成“当我向上滚动时,向上滚动的视口部分小于当前显示的屏幕部分。”。这种“理论”有效,但仅在向上滚动的内容部分大于显示的实际内容部分之前。一旦达到这一点,我的“理论”就不再有意义了。

2号桥

  • 为什么需要最后一条语句:prev = current;?我注意到如果我不写最后一条语句,导航栏会在我向上滚动时隐藏,但当我向下滚动时它将不显示 了。

sn-p

const burger = document.querySelector('.burger');
const nav = document.querySelector('nav');

burger.addEventListener('click', () => {
  nav.classList.toggle('active');
  burger.classList.toggle('hide');
  xicon.classList.toggle('active');
});

const xicon = document.querySelector('.xicon');
xicon.addEventListener('click', function() {
  nav.classList.toggle('active');
  xicon.classList.toggle('active');
  burger.classList.toggle('hide');
})



const header = document.querySelector('header');
let prev = window.pageYOffset;

window.addEventListener('scroll', function(){
  let current = window.pageYOffset;
  if(prev < current){
    header.classList.add('hide');
  }
  else {
    header.classList.remove('hide');
    }

    prev = current;

})
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.logoandicon {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: powderblue;
  padding: .7em 0;
}

.logo {
  margin-left: .5em;
}

.burger {
  margin-right: 1em;
  z-index: 2;
}

.burger.hide {
  display: none;
}

nav ul li a {
  text-decoration: none;
  color: black;
  font-family: verdana;
}

nav ul li {
  text-align: center;
  list-style: none;
}

nav {
  padding: 1em 0;
  line-height: 2em;
  background: lightgreen;
  display: none;
}

nav.active {
  display: block;
}

.xicon {
  position: absolute;
  right: 1em;
  display: none;
}

.xicon.active {
  display: block;
}

header {
  width: 100vw;
  position: fixed;
}

header.hide {
  display: none;
}

main {
  padding-top: 4em;
}
  <header>
    <div class="logoandicon">
      <h1 class="logo">Logo</h1>
      <img src="menu.svg" class="burger" width="30px" alt="burger-icon">
      <img src="xicon.svg" class="xicon" width="27px" alt="x-icon">
    </div>
    <nav>
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">About Us</a></li>
        <li><a href="#">Contacts</a></li>
      </ul>
    </nav>
  </header>
  <main>
    <h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Porro ut, animi iure sequi voluptatem maiores, aspernatur tempora, ipsa tempore, voluptate sint. Maiores quos inventore cumque reiciendis iusto illum, aut quam, suscipit temporibus veniam. Reprehenderit distinctio velit eveniet blanditiis, animi optio voluptas dolores repellendus ad itaque veritatis. Expedita deserunt, ab dolor accusamus sequi eum optio. Fuga dolorum, quod qui laboriosam iure molestiae magnam explicabo! Accusamus, alias, non. Eius voluptas in aspernatur natus illo et possimus optio, cupiditate saepe quisquam totam laboriosam ullam nihil consequatur rem earum ratione perspiciatis. Quo impedit ipsum assumenda suscipit unde inventore dolores quas? Ipsa aliquam sapiente rerum sit autem magni ad dolore iste vero optio saepe, impedit eveniet suscipit, deserunt. Modi architecto laudantium placeat beatae repellat harum deleniti facere deserunt officia unde mollitia error praesentium, sunt fugit recusandae soluta facilis earum voluptatem libero consectetur illum debitis quos! Odit unde, quo non blanditiis vitae aperiam obcaecati provident praesentium quas qui, veritatis enim accusamus iusto rerum harum porro maxime sit amet cum odio suscipit ipsum nulla adipisci. Totam consectetur quas ipsa. Natus officiis, eveniet reprehenderit neque rem sint eum, ratione, numquam blanditiis nisi culpa repudiandae nemo beatae. Ea cum officiis vel, sed distinctio, voluptatibus quibusdam! Soluta voluptate, atur tempora, ipsa tempore, voluptate sint. Maiores quos inventore cumque reiciendis iusto illum, aut quam, suscipit temporibus veniam. Reprehenderit distinctio velit eveniet blanditiis, animi optio voluptas dolores repellendus ad itaque veritatis. Expedita deserunt, ab dolor accusamus sequi eum optio. Fuga dolorum, quod qui laboriosam iure molestiae magnam explicabo! Accusamus, alias, non. Eius voluptas in aspernatur natus illo et possimus optio, cupiditate saepe quisquam totam laboriosam ullam nihil consequatur rem earum ratione perspiciatis. Quo impedit ipsum assumenda suscipit unde inventore dolores quas? Ipsa aliquam sapiente rerum sit autem magni ad dolore iste vero optio saepe, impedit eveniet suscipit, deserunt. Modi architecto laudantium placeat beatae repellat harum deleniti facere deserunt officia unde mollitia error praesentium, sunt fugit recusandae soluta facilis earum voluptatem libero consectetur illum debitis quos! Odit unde, quo non blanditiis vitae aperiam obcaecati provident praesentium quas qui, veritatis enim accusamus iusto rerum harum porro maxime sit amet cum odio suscipit ipsum nulla adipisci. Totam consectetur quas ipsa. Natus officiis, eveniet reprehenderit neque rem sint eum, ratione, numquam blanditiis nisi culpa repudiandae nemo beatae. Ea cum officiis vel, sed distinctio, voluptatibus quibusdam! Soluta voluptate, non facilis?</h1>
  </main>


<script src="main.js">

</script>

【问题讨论】:

    标签: javascript html css scroll dom-events


    【解决方案1】:

    我会尽力解释,然后提供注释掉的代码。

    这不完全是视口的高度,window.pageYOffset 计算您从窗口顶部向下滚动了多远。当您加载页面时,该数字为 0。我建议您查看MDN Docs

    然后,当您滚动时,您当前的偏移量设置为 prev,而您的新偏移量设置为当前。您可以尝试console.log(current, prev) 并查看它在您上下滚动时的变化。当 prev 和 current 都有值时,它们会被比较,如果 current &gt; prev,它会显示元素。

    prev = current 负责保存您之前的偏移量,因此可以将新的当前值与之进行比较。

    const header = document.querySelector("header");
    let prev = window.pageYOffset; // 0 when page loads, otherwise stores previous 'current' value
    
    window.addEventListener("scroll", function () {
      let current = window.pageYOffset; // your current offset from the top of the document
    
      // Add console.log(current, prev) here if you want to see how the offset changes, you'll notice that prev value is always smaller when you scroll down and bigger when you scroll up
    
      if (prev < current) {
        header.classList.add("hide");
      } else {
        header.classList.remove("hide");
      }
    
      prev = current; // Set current variable to prev variable so there's something to compare
    });
    

    【讨论】:

    • 非常感谢。这段代码是否有一个简单的改进来使导航栏仅在我滚动时才隐藏,比如说 50px?我尝试在 if 语句中输入 50,但不起作用
    • @marcomarco 如果我理解正确,您需要一个变量来存储偏移量,但仅在向上滚动时,然后将当前变量与向下滚动时的变量进行比较。 cmets 中真的没有空间,所以我做了一个codepen 并留下了一些 cmets 供您关注
    • 你真好!非常感谢,真的! :)
    • @marcomarco 肯定的 :) 我实际上也是同时学的。我很想发布如何做到这一点,所以它只适用于页面顶部的偏移量,但不适用于任何地方,但后来我虽然“我知道我已经看到应用程序和一些页面之前这样做过,所以它不可能这么难”。确实进行了一段时间的实验。
    【解决方案2】:

    Point n°1 - 当页面加载时,pageYOffset 值被分配给prev 变量,并且滚动事件监听器被激活。因此,当您滚动当前 pageYOffset 值时,会将其分配给 current 变量,然后将其与 prev 变量进行比较。因此,正如条件所说,如果prev 值小于current,则隐藏导航栏,否则显示导航栏。 示例 - 当页面加载时,prev 的值将被分配为 0。当您滚动时,它会大于 0。

    Point n°2 - 每次滚动时,事件都会运行该函数。因此,当您向下滚动时,current 值每次都会更新。因此,使用 prev = current 您将 current 值存储到 prev 值中。这让用户可以在他/她向上滚动时获得滚动条。 示例 - 用户向下滚动,current 的值存储到 prev。假设它为current = 220,它存储在prev。所以当用户向上滚动时,current 的值将是 215。所以prev 将大于current 并显示导航栏。

    【讨论】:

      【解决方案3】:

      在解释你的代码之前,你需要了解What is window.pageYOffset and how is work。如果你想在javascript中更多地自定义其他事件,你必须学习windowaddEventListener。当你学会了,你会清楚这些代码是做什么的并且你可以在 javascript 中使用滚动来做很多事情。

      您可以在javascript中使用console.log(SomeThing)进行调试。然后您可以逐步检查。示例:

      const header = document.querySelector('header');
      
      let prev = window.pageYOffset;
      console.log("Start State for prev:" + prev); //debug for initial point
      
      window.addEventListener('scroll', function(){
      
      let current = window.pageYOffset;
      console.log("Current State for current:" + current); //debug for current point when you scroll
      
      // you will see which condition is happen now 
      // when you start scroll down "prev" is always smaller than "current".So condition is true, header will hide.
      // when you scroll up "prev" is always smaller than "current".So condition is true, header will hide.
      
      if(prev < current){
          header.classList.add('hide');
      }
      else {
          header.classList.remove('hide');
      }
      
      //But you want to show scroll up, you need to put current to prev.
      prev = current;
      
      })
      

      window.pageYOffset 返回从 0 开始的某个点。向下滚动时,window.pageYOffset 返回点增加。向上滚动时,window.pageYOffset 返回点减少。因为如果不使用,则使用 window.addEventListener 滚动'不在滚动事件中使用。 window.pageYOffset 返回点不会改变。因此,prev 值将固定,因为它有一次调用。 current 值会在使用滚动时发生变化。当您了解上述代码的工作原理后,您可以查看以下答案以获得您的积分。

      点 n°1

      第一次,您调用这些 javascript,prev 获取一些值。假设prev 获取“0”。这将是修复。 current 得到一些与prev 相同的值。所以,条件是假的。 header 不会隐藏。当您向下滚动时,current 的值会增加。 prev 值相同。所以,条件为真。 header 将隐藏。当您向上滚动时,current 值会减小。 prev 值相同。当current 更改为'0'值。条件为假时,header 不会隐藏。

      第 2 点

      您想在向上滚动时取消隐藏。您需要将prev 的值设置为高于current。向上滚动是减少。让current 为'10',prev 赋值为'10'。下一次,current 将减少'9'。 prev 为 '10'。条件为 false。header 不会隐藏。因此,您需要将 current 分配给 prev

      【讨论】:

        猜你喜欢
        • 2017-03-03
        • 1970-01-01
        • 2019-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多