Web 功能:
scrollend
在网页上滚动时,应顺畅且响应迅速。在滚动期间执行繁重的任务(例如布局重新计算、分析数据信标跟踪或动态 DOM 更新)可能会使主线程饱和,从而导致丢帧和布局抖动。
一直以来,开发者都依赖于使用 setTimeout() 对 scroll 事件进行去抖动,以猜测滚动何时结束。不过,众所周知,这些去抖动函数并不可靠。它们可能会在用户仍在滚动时触发。
scrollend 事件提供了一种高度可靠、以效果为导向的解决方案。当滚动停止、所有过渡完成且轻触手势释放时,浏览器会触发 scrollend 事件。
如何实现
如需实现延迟工作模式,请执行以下操作:
- 设置可滚动容器:使用
overflow: auto或overflow: scroll创建容器。 - 监听
scroll事件:仅将此监听器用于基本动态指标或信息性布局样式。请勿在此处执行繁重的工作。 - 监听
scrollend事件:在滚动容器或文档本身上注册scrollend回调。 - 在回调中执行耗时的工作:此时可以安全地提取动态内容或触发全面的 DOM 布局。
示例代码
.scroll-container {
height: 300px;
overflow-y: auto;
}
const scroller = document.querySelector('.scroll-container');
// 1. Informative feedback during scroll
scroller.addEventListener('scroll', () => {
// Avoid dynamic heavier data updates here
console.log('Scrolling dynamically... updates deferred');
});
// 2. Safe callback when scrolling rests
scroller.addEventListener('scrollend', () => {
// Run layout recalculations or analytical beacons updates here
const currentVisibleSection = findMostVisibleSection(scroller);
fetchAdditionalData(currentVisibleSection);
});
策略性实施和最佳实践
- 务必在触发布局数据信标或动态提取新内容布局时使用
scrollend,而不是去抖动的scroll事件。 - 务必考虑将此功能与
scrollSnapChange或scrollSnapChanging贴靠互动搭配使用,以便构建轮播界面或客户评价库幻灯片。 - 请勿在动态视觉滚动回调中捆绑依赖于布局的动态更新。
- 务必考虑视觉视口缩放和滚动是否会正确触发
scrollend事件。
后备策略
对于不受支持的浏览器,请回退到使用 setTimeout 的去抖动 scroll 事件,以分派自定义 scrollend 事件。
function initializeDemo() {
const scroller = document.querySelector('#scroller');
scroller.addEventListener('scrollend', () => {
// Safe execution
});
}
if ('onscrollend' in window) {
initializeDemo();
} else {
initializeDemo();
const scroller = document.querySelector('#scroller');
scroller.addEventListener('scroll', () => {
clearTimeout(window.scrollendtimer);
window.scrollendtimer = setTimeout(() => {
scroller.dispatchEvent(new CustomEvent('scrollend'));
}, 100);
});
}