为什么窗口滚动事件没有被触发?

7

我有这个 js 类:

export class ScrollBehaviorComponent {
  init() {
    const body = document.querySelector('body')
    let previousScroll = window.pageYOffset || 0
    let scrollDirIsUp = false

    window.addEventListener('scroll', function(e) {
      const currentScroll = window.pageYOffset // never gets updated
      scrollDirIsUp = currentScroll > 0 && previousScroll >= currentScroll // never gets updated
      body.classList.toggle('body--scroll-up', scrollDirIsUp) // never gets updated

      alert('scroll is up: ', window.pageYOffset) // never happens
    })

    console.log(window) // I see this log, o_0
  }
}

export default ScrollBehaviorComponent

我之前已经使用过它,但是对于这个具体项目,事件没有被触发。

我是这样加载它的:

import ScrollBehaviorComponent from 'Shared/scroll-behavior/scroll-behavior.component'

export const HomeModule = {
  init() {
    new ScrollBehaviorComponent().init()

    // rest of page's code..
  },
}

问题是开发人员控制台没有报错,但事件也从未触发。即使我在开发人员控制台输入命令(同样没有错误)。
window.window.addEventListener('scroll', function(e) {
  console.log('scroll is up: ', window.pageYOffset) // never happens
})

我正在输入的时候,stackoverflow 上发生了什么?

在这里输入图片描述

可能的原因是什么?应用程序中是否有阻止事件传播的地方?如果是这样,有什么线索可以找到它吗?还有其他猜测吗?(这是一个继承来的项目)


正如有人提到的,可能是由于滚动的上下文不正确,也许您在不同的元素上滚动并监听窗口。也许您可以尝试使用新的Intersection Observable API(链接)。我认为它比窗口滚动事件更好用。但这只是一个小提示。 - amaj
4个回答

18

可能是某个元素(如 body 本身或某个嵌套的 div)设置了 css 属性 overflowscroll

为了尝试确定是哪个元素,您可以添加类似以下内容的代码:

document.querySelectorAll("*").forEach(
  element => element.addEventListener("scroll",
    ({target}) => console.log(target, target.id, target.parent, target.parent.id)
  )
);

一定要在页面完全渲染后运行它;然后在控制台中,您应该有足够的数据来识别正在滚动的元素。


即使我不得不将 getElementsByTagName 改为 querySelectorAll,并将 foreach 改为 forEach,但它还是有助于解决问题。非常感激。 - Toni Michel Caubet
嗨@ToniMichelCaubet,如果这真的有帮助解决问题,我可以请求在悬赏到期之前亲切地接受答案吗? - Daniele Ricci
我宁愿多等一会儿。另外,我建议您编辑您的答案并进行修复(您的代码无法正常工作)。 - Toni Michel Caubet
1
这个答案也帮助了别人两年,感谢 @DanieleRicci。 - Vivek K.

5

window 在没有发生 scroll 事件的情况下是无法滚动的。您可以通过在开发者工具中单击 <!DOCTYPE html> 元素(也可以运行 getEventListeners(window).scroll)来验证某些第三方代码是否已移除了事件监听器:

enter image description here

如果您看到事件监听器,那么在您的应用程序中,实际上正在滚动另一个元素:

完整页面窗口滚动的示例:

window.addEventListener('scroll', function() {
  console.log('Scroll event');
});
#big-content {
    height: 1000px;
}
<div id="big-content">
</div>

一个例子,你可能认为在滚动窗口,但实际上滚动的是一个完整页面的底层元素:

window.addEventListener('scroll', function(e) {
  console.log('Underlying element scroll event bubbled'); // never happens
});

document.getElementById('container').addEventListener('scroll', function({ bubbles }) {
    console.log('Will bubble: ', bubbles);
});
#container {
    position: fixed;
    height: 100vh;
    width: 100vw;
    overflow: scroll;
}

#big-content {
    height: 1000px;
}
<div id="container">
    <div id="big-content">
    </div>
</div>

在这种情况下,事件不会向上冒泡,你无法在 window 级别监听到它。

4

这可能是由于元素滚动不是在body上。以这段代码为例。我将滚动绑定到了body,但由于元素滚动的是div而不是body,所以该元素不会被触发。您应该检查您的样式和dom。

document.body.addEventListener('scroll', () => {
  console.log('Hi')
  const elem = document.createElement('div');
  elem.innerText = 'Hi';
  document.body.appendChild(elem);
});
<html>
  <body>
    <main style="height: 3000px">
      <div>Hello</div>
      <div>This</div>
      <div>Is</div>
      <div>A</div>
      <div>Test</div>
    </main>
  </body>
</html>


1
在我的情况下,它与页面主体有关。由于页面主体具有100%的高度。 - MrEduar

1

在上一个项目中,我遇到了这个问题。您需要填写HTML引用的报价。解决方案是:

   import HomeModule from "./home";
    HomeModule.init();
    document.getElementById("app").innerHTML = `<div class="page__inner"><main class="main main_width-limit"><header class="main__header"><div class="main__header-inner"><div class="main__header-group"><ol class="breadcrumbs"><li class="breadcrumbs__item breadcrumbs__item_home"><a class="breadcrumbs__link" href="/"><span class="breadcrumbs__hidden-text">Tutorial</span></a></li><li class="breadcrumbs__item" id="breadcrumb-1"><a class="breadcrumbs__link" href="/ui"><span>Browser: Document, Events, Interfaces</span></a></li><li class="breadcrumbs__item" id="breadcrumb-2"><a class="breadcrumbs__link" href="/event-details"><span>UI Events</span></a></li><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Tutorial","item":"https://javascript.info/"},{"@type":"ListItem","position":2,"name":"Browser: Document, Events, Interfaces","item":"https://javascript.info/ui"},{"@type":"ListItem","position":3,"name":"UI Events","item":"https://javascript.info/event-details"}]}</script></ol><div class="updated-at" data-tooltip="Last updated at 2nd December 2019"><div class="updated-at__content">2nd December 2019</div></div></div><h1 class="main__header-title">Scrolling</h1></div></header><div class="content"><article class="formatted" itemscope="" itemtype="http://schema.org/TechArticle"><meta itemprop="name" content="Scrolling"><div itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="email" content="iliakan@gmail.com"><meta itemprop="name" content="Ilya Kantor"></div><div itemprop="articleBody"><p>The <code>scroll</code> event allows to react on a page or element scrolling. There are quite a few good things we can do here.</p>
<p>For instance:</p>
<ul>
<li>Show/hide additional controls or information depending on where in the document the user is.</li>
<li>Load more data when the user scrolls down till the end of the page.</li>
</ul>
<p>Here’s a small function to show the current scroll:</p>
<div data-trusted="1" class="code-example" data-autorun="true" data-prism-highlighted="1">
      <div class="codebox code-example__codebox">
        
        <div class="codebox__code" data-code="1">
          <pre class="line-numbers  language-javascript"><code class=" language-javascript">window<code class="token punctuation">.</code><code class="token function">addEventListener</code><code class="token punctuation">(</code><code class="token string">'scroll'</code><code class="token punctuation">,</code> <code class="token keyword">function</code><code class="token punctuation">(</code><code class="token punctuation">)</code> <code class="token punctuation">{</code>
  document<code class="token punctuation">.</code><code class="token function">getElementById</code><code class="token punctuation">(</code><code class="token string">'showScroll'</code><code class="token punctuation">)</code><code class="token punctuation">.</code>innerHTML <code class="token operator">=</code> window<code class="token punctuation">.</code>pageYOffset <code class="token operator">+</code> <code class="token string">'px'</code><code class="token punctuation">;</code>
<code class="token punctuation">}</code><code class="token punctuation">)</code><code class="token punctuation">;</code></code><span class="line-numbers-rows"><span></span><span></span><span></span></span></pre>
        </div>
      </div>
      
      </div><p>In action:</p>
<p>Current scroll = <b id="showScroll">43.20000076293945px</b></p>
<p>The <code>scroll</code> event works both on the <code>window</code> and on scrollable elements.</p>
<h2><a class="main__anchor" name="prevent-scrolling" href="#prevent-scrolling">Prevent scrolling</a></h2><p>How do we make something unscrollable?</p>
<p>We can’t prevent scrolling by using <code>event.preventDefault()</code> in <code>onscroll</code> listener, because it triggers <em>after</em> the scroll has already happened.</p>
<p>But we can prevent scrolling by <code>event.preventDefault()</code> on an event that causes the scroll, for instance <code>keydown</code> event for <kbd class="shortcut">pageUp</kbd> and <kbd class="shortcut">pageDown</kbd>.</p>
<p>If we add an event handler to these events and <code>event.preventDefault()</code> in it, then the scroll won’t start.</p>
<p>There are many ways to initiate a scroll, so it’s more reliable to use CSS, <code>overflow</code> property.</p>
<p>Here are few tasks that you can solve or look through to see the applications on <code>onscroll</code>.</p>
</div></article><div class="tasks formatted"><h2 class="tasks__title" id="tasks"><a class="tasks__title-anchor main__anchor main__anchor main__anchor_noicon" href="#tasks">Tasks</a></h2><div class="task tasks__task"><div class="task__header"><div class="task__title-wrap"><h3 class="task__title"><a class="main__anchor" href="#endless-page" name="endless-page">Endless page</a></h3><a class="task__open-link" href="/task/endless-page" target="_blank"></a></div><div class="task__header-note"><span class="task__importance" title="How important is the task, from 1 to 5">importance: 5</span></div><div class="task__content"><p>Create an endless page. When a visitor scrolls it to the end, it auto-appends current date-time to the text (so that a visitor can scroll more).</p>
<p>Like this:</p>`

它正常工作。

滚动结果


我认为这不是同一个问题(同时你的代码由于在模块外部导入而崩溃..) - Toni Michel Caubet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接