<p>判断页面滚动到底部需用 window.scrollY + window.innerHeight >= document.body.scrollHeight - threshold(如100px)并节流,fetch后用append()安全插入DOM,防重复请求用isLoading开关配合finally,iOS需加-webkit-overflow-scrolling: touch或改用body滚动。</p>

怎么判断页面已经滚动到底部
核心是监听 window.onscroll 或 addEventListener('scroll'),但不能只看 window.scrollY + window.innerHeight 是否等于 document.body.scrollHeight——这个等式在很多浏览器(尤其是 iOS Safari)里因渲染延迟或缩放而经常不成立。
稳妥做法是留一个余量(比如 100px),用「距离底部小于等于该值」作为触发条件:
const threshold = 100; const isAtBottom = window.scrollY + window.innerHeight >= document.body.scrollHeight - threshold;
- 别用
document.documentElement.scrollHeight,IE 和部分移动端行为不一致,统一用document.body.scrollHeight - 滚动事件高频触发,务必加节流(
setTimeout或requestAnimationFrame),否则卡顿明显 - 首次加载完内容后,
scrollHeight会变大,但新 DOM 插入后需确保重排完成再判断,否则可能误判
fetch 加载数据后怎么安全插入 DOM
直接 innerHTML += ... 会清空已有绑定的事件监听器、销毁已挂载的 React/Vue 组件,还可能引发内存泄漏。必须用 append() 或 insertAdjacentElement()。
假设你用 fetch 拿到的是 JSON 数组,渲染成 <li> 列表:
立即学习“前端免费学习笔记(深入)”;
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
const listEl = document.getElementById('item-list');
data.forEach(item => {
const li = document.createElement('li');
li.textContent = item.title;
listEl.append(li); // ✅ 安全追加
});- 避免在循环里反复读取
listEl.innerHTML,性能差;用文档片段(DocumentFragment)批量插入更优 - 如果后端返回的是完整 HTML 字符串,用
insertAdjacentHTML('beforeend', htmlStr)比innerHTML +=稍安全,但仍需注意 XSS,务必服务端转义或前端用DOMPurify - 插入后记得调用
listEl.scrollTop = listEl.scrollHeight?不用——用户正在滚动,强行改 scrollTop 会打断体验
怎么防止重复请求和加载中状态错乱
用户快速滚动时,很容易连续触发多次「到底部」判断,导致发多个重复请求。必须加开关控制。
最简方案:用布尔变量 isLoading 锁住请求入口:
let isLoading = false;
<p>function loadMore() {
if (isLoading) return;
isLoading = true;</p><p>fetch('/api/items?offset=...')
.then(r => r.json())
.then(data => {
renderItems(data);
})
.finally(() => isLoading = false);
}- 不要把
isLoading = false放在.then()里——出错就永远锁死;必须用.finally()或try/finally - 后端分页建议用游标(cursor)而非
offset,避免大数据量下offset越往后越慢 - 加载中可以加个 loading 元素(如
<div id="loading" style="display:none">...),但显示/隐藏逻辑要和isLoading严格同步,别漏掉.finally()里的隐藏操作
移动端 iOS 上滚动事件不触发怎么办
iOS Safari 对非 body 滚动容器的 scroll 事件支持极差,尤其当父容器设了 overflow-y: scroll 且没加 -webkit-overflow-scrolling: touch 时,事件几乎不触发。
两种解法:
- 强制让整个页面由
body滚动:移除所有自定义滚动容器,用min-height: 100vh+body自然滚动(最简单,兼容性最好) - 若必须局部滚动(如弹窗内列表),给滚动容器加:
overflow-y: scroll; -webkit-overflow-scrolling: touch;
并监听该容器的scroll事件,而不是window - 别信
touchmove代替scroll——它无法准确判断是否到底部,且会干扰原生滚动惯性
真正麻烦的不是代码写不对,而是 iOS 上 scrollHeight 在动态插入内容后可能延迟更新,得等一帧(requestAnimationFrame)再判断。


















