删除超时函数并摆脱其 bug,您真正需要的是:scrollend 事件。
在 scrollend
事件发生之前,没有可靠的方法来检测滚动行为
已完成。这意味着事件会延迟触发,或者在用户的手指仍按在屏幕上时触发。由于了解滚动操作的时间
会导致错误并给用户带来糟糕的体验。
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
此 setTimeout()
策略能做到最好,就是了解滚动操作是否已在
100ms
。这更像是滚动已暂停事件,而不是滚动已结束事件。
在
scrollend
事件,浏览器会为您执行所有这些高难度的评估。
document.onscrollend = event => {…}
太好了。恰到好处地把握时间,充分满足有意义的条件 然后再发出信号
试试看!
活动详情
在以下情况下,系统会触发 scrollend
事件:
- 浏览器不再滚动动画或滚动平移。
- 用户的触摸已被释放。
- 用户的指针已释放滚动拇指。
- 用户的按键已释放。
- 滚动到 fragment 已完成。
- 滚动贴靠已完成。
- scrollTo()
已完成。
- 用户已滚动视觉视口。
在以下情况下不会触发 scrollend
事件:
- 用户的手势未导致任何滚动位置发生变化(未发生任何平移)。
- scrollTo()
未找到任何翻译。
这个事件之所以要在 Web 平台上花费这么长的时间,是因为
这些小细节需要规范详细信息最复杂的方面之一是阐明视觉视口与文档的 scrollend
详细信息。假设您正在放大某个网页。在这种放大状态下,您可以滚动浏览,但不一定是滚动文档。请放心,即使是由用户驱动的可见视口滚动
互动会在完成后发出 scrollend
事件。
使用事件
与其他滚动事件一样,您可以通过多种方式注册监听器。
addEventListener("scrollend", (event) => {
// scroll ended
});
aScrollingElement.addEventListener("scrollend", (event) => {
// scroll ended
});
或者,使用 event 属性:
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
事件(如果有)。如果不可用,脚本会监视指针事件并
以便尽可能准确地估算结束它的事件。
使用场景
最好避免在滚动时执行计算密集型工作。这种做法可确保滚动操作可以自由使用尽可能多的内存
以便保持流畅的体验使用 scrollend
事件提供了一个绝佳的时机来调用并执行繁重的工作,因为滚动操作已停止。
scrollend
事件可用于触发各种操作。一个常见用例是将关联的界面元素与滚动停止的位置同步。例如:
- 将轮播界面滚动位置与圆点指示符同步。
- 将图库项与其元数据同步。
- 在用户滚动到新标签页后提取数据。
设想一个场景,例如用户滑开电子邮件。完成后 然后根据他们滚动到的位置执行操作。
您还可以使用此事件在程序化购买或用户购买发生后 滚动或记录分析等操作。
这便是一个很好的示例。在该示例中,箭头、点和焦点等多个元素 需要根据滚动位置进行更新。观看我如何在 YouTube 上制作此轮播界面。此外,您还可以试用实时演示版。
感谢 Mehdi Kazemi 在工程方面的工作,以及 Robert Flack 提供 API 和实现方面的指导。