使用Vanilla JavaScript实现移动端无限滚动触发失效问题求解
问题根因
- 移动端浏览器的地址栏、底部工具栏会动态收缩/展开,
document.documentElement.clientHeight计算的视口高度会随之波动,原代码中scrollTop + clientHeight >= scrollHeight的严格触底判断很难命中 - 部分移动端浏览器的滚动橡皮筋效果会导致触底时
scrollTop取值出现瞬时偏差,无法满足判断条件 - 少数浏览器中滚动距离需要从
document.body.scrollTop取值,仅读取document.documentElement.scrollTop可能拿到0值
修复方案
方案1:修改原有滚动监听逻辑(低成本适配)
- 给触底判断增加缓冲阈值,不需要完全触底就提前触发请求,同时兼容不同浏览器的scrollTop取值
- 增加加载状态锁,避免滚动过程中重复触发接口请求
修改后代码如下:
// 全局定义加载状态锁,避免重复请求 let isLoading = false; window.addEventListener("scroll", () => { const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; const { scrollHeight, clientHeight } = document.documentElement; // 100px为缓冲阈值,可根据业务需求调整大小 if (scrollTop + clientHeight >= scrollHeight - 100 && !isLoading) { isLoading = true; showLoading(); } }); // 原有请求逻辑中新增锁重置的逻辑 function showLoading() { // 调用TMDB API拉取数据的原有逻辑 fetch(/* 你的TMDB请求地址 */) .then(res => res.json()) .then(data => { // 原有数据渲染逻辑 // ... }) .finally(() => { // 请求结束后重置加载状态,允许下次触发 isLoading = false; }) }
方案2:使用Intersection Observer实现(性能更优、兼容性好)
如果不想手动处理滚动计算的各种兼容问题,可以用原生Intersection Observer API实现,性能远高于高频scroll事件监听,且天然适配各端视口差异:
- 首先在列表末尾新增一个触发加载的占位元素:
<ul id="movieList"> <!-- 原有电影列表内容 --> </ul> <!-- 加载触发锚点 --> <div id="loadTrigger"></div>
- 替换原有scroll监听逻辑为Observer监听:
let isLoading = false; const loadTrigger = document.querySelector('#loadTrigger'); const observer = new IntersectionObserver((entries) => { // 锚点元素进入视口且不在加载状态时触发请求 if (entries[0].isIntersecting && !isLoading) { isLoading = true; showLoading(); } }); // 监听锚点元素 observer.observe(loadTrigger); // showLoading函数的逻辑和方案1中一致,请求结束后重置isLoading即可
内容的提问来源于stack exchange,提问作者Antoni0Zac
相关产品推荐
相关产品推荐

