Scrollend(一种新的 JavaScript 事件)

删除超时函数并消除其 bug,以下是您真正需要的事件:scrollend。

在 scrollend 事件之前,没有可靠的方法来检测滚动是否完成。这意味着事件会延迟触发,或者在用户的手指仍停留在屏幕上时触发。由于无法可靠地知道滚动何时实际结束,因此会导致 bug 和糟糕的用户体验。

之前
document.onscroll = event => {
  clearTimeout(window.scrollEndTimer)
  window.scrollEndTimer = setTimeout(callback, 100)
}

此 setTimeout() 策略最多只能知道滚动是否已停止 100ms。这使得它更像是滚动已暂停事件,而不是滚动已结束事件。

在 scrollend 事件之后,浏览器会为您完成所有这些困难的评估。

之后
document.onscrollend = event => {…}

这才是好东西。在发出之前,时机恰到好处,且包含大量有意义的条件。

Browser Support

  • Chrome: 114.
  • Edge: 114.
  • Firefox: 109.
  • Safari: 26.2.

Source

试试看!

活动详情

scrollend 事件会在以下情况下触发: - 浏览器不再为滚动添加动画效果或转换滚动。 - 用户的轻触已释放。 - 用户的指针已释放滚动滑块。 - 用户已松开按键。 - 滚动到片段已完成。 - 滚动贴靠已完成。 - scrollTo() 已完成。 - 用户滚动了可视视口。

在以下情况下,scrollend 事件不会触发: - 用户的操作未导致任何滚动位置变化(未发生平移)。 - scrollTo() 未生成任何翻译。

此事件之所以花了这么长时间才进入 Web 平台,是因为有许多小细节需要规范细节。其中一个最复杂的领域是阐明视觉视口与文档的 scrollend 详细信息。假设您放大了一个网页。您可以在此缩放状态下滚动,但不一定会滚动文档。请放心,即使是这种由用户驱动的视觉视口滚动互动,在完成后也会发出 scrollend 事件。

使用事件

与其他滚动事件一样,您可以通过多种方式注册监听器。

addEventListener("scrollend", (event) => {
  // scroll ended
});

aScrollingElement.addEventListener("scrollend", (event) => {
  // scroll ended
});

或使用事件属性:

document.onscrollend = (event) => {
  // scroll ended
};

aScrollingElement.onscrollend = (event) => {
  // scroll ended
};

Polyfill 和渐进增强

如果您现在就想使用这一新事件,请参考我们的最佳建议。您可以继续使用当前的滚动结束策略(如果有),并在其开头使用以下代码检查支持情况:

'onscrollend' in window
// true, if available

这将根据浏览器是否提供该事件来报告 true 或 false。通过此检查,您可以对代码进行分支:

if ('onscrollend' in window) {
  document.onscrollend = callback
}
else {
  document.onscroll = event => {
    clearTimeout(window.scrollEndTimer)
    window.scrollEndTimer = setTimeout(callback, 100)
  }
}

这是一个良好的开端,有助于在 scrollend 事件可用时逐步增强该事件。您也可以尝试使用我制作的 polyfill (NPM),它能让浏览器发挥最佳性能:

import {scrollend} from "scrollyfills"

// then use scrollend as if it's existed this whole time
document.onscrollend = callback

该 polyfill 将逐步增强,以使用浏览器内置的 scrollend 事件(如果有)。如果该 API 不可用,脚本会监控指针事件和滚动,以尽可能准确地估算事件结束时间。

使用场景

最好避免在滚动时执行计算量繁重的工作。这种做法可确保滚动操作能够尽可能多地使用内存和处理能力,从而保持流畅的体验。使用 scrollend 事件是调用和执行繁重工作的绝佳时机,因为此时滚动已停止。

scrollend 事件可用于触发各种操作。一种常见的使用场景是,将关联的界面元素与滚动停止的位置同步。例如: - 将轮播界面滚动位置与圆点指示器同步。 - 将图库内容与其元数据同步。 - 在用户滚动到新标签页后提取数据。

想象一下用户滑走电子邮件的场景。在用户完成滑动后,您就可以根据他们滚动到的位置执行操作。

您还可以使用此事件在程序化或用户滚动后进行同步,或执行日志分析等操作。

下面是一个很好的示例,其中需要根据滚动位置更新多个元素,例如箭头、圆点和焦点。在 YouTube 上观看我如何构建此轮播界面。此外,您还可以试用实时演示。

感谢 Mehdi Kazemi 在此方面所做的工程工作,以及 Robert Flack 提供的 API 和实现指导。