应使用容差阈值判断滚动到底部,即window.scrolly + window.innerheight >= document.body.scrollheight - threshold(threshold常见50–100px),避免因布局重排延迟或小数像素导致等式失效;必须用document.body.scrollheight;推荐优先使用intersectionobserver替代scroll事件,并注意ios/android webview中滚动容器非window的陷阱。

用 window.scrollY + window.innerHeight >= document.body.scrollHeight - threshold 判断是否到底部
直接比较 window.scrollY + window.innerHeight === document.body.scrollHeight 在 iOS Safari、Chrome 移动版、部分缩放/字体渲染场景下会失效——因为 scrollHeight 可能因布局重排延迟一帧,或小数像素四舍五入导致等式不成立。
稳妥做法是引入一个容差阈值(threshold),常见取值 50–100px:
const threshold = 100; const isAtBottom = window.scrollY + window.innerHeight >= document.body.scrollHeight - threshold;
注意必须用 document.body.scrollHeight,不要用 document.documentElement.scrollHeight:后者在 IE 和某些移动端 WebView 中返回不一致(比如始终为视口高度)。
为什么不能只监听 scroll 事件就开 fetch
滚动事件高频触发(每秒几十次),不做节流或防抖,fetch 请求可能并发堆积、重复发起、甚至覆盖上一次响应结果。
关键控制点有三个:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 用布尔变量
isLoading防止重复请求,fetch 前先检查if (isLoading || !hasMore) return - 在
fetch().finally(() => isLoading = false)中统一归零状态,避免异常中断后卡死 - 服务端返回空数据或
next_cursor: null时,显式设hasMore = false,否则用户反复滚动会静默失败
用 IntersectionObserver 替代 scroll 监听更可靠
scroll 事件依赖主线程,页面复杂时容易丢帧、延迟触发;IntersectionObserver 是异步、低优先级、原生性能优化的方案,尤其适合长列表和低端 Android 设备。
实操要点:
- 底部占位元素必须存在且可被观测:
<div id="infinite-loader" style="height: 1px"></div> - 观察器需配置
rootMargin: '0px 0px -100px 0px',让“进入视口”提前 100px 触发(模拟 threshold) - 兼容性 fallback:若
IntersectionObserver不可用(如 IE11),再降级到scroll监听
示例判断逻辑:
const observer = new IntersectionObserver(entries => {
if (entries[0].isIntersecting && !isLoading && hasMore) {
loadMore();
}
}, { rootMargin: '0px 0px -100px 0px' });
observer.observe(document.getElementById('infinite-loader'));
iOS 和某些安卓 WebView 的滚动容器陷阱
默认情况下,iOS Safari 对 body 滚动做了特殊处理:overflow: auto 的父容器(比如某个 <div class="list">)滚动时,<code>window.scrollY 始终为 0,导致所有基于 window 的检测完全失效。
两种解法:
- 强制让整个页面由
body滚动:移除所有自定义滚动容器,CSS 中确保html, body { height: 100%; overflow: hidden; },内容区用position: absolute; top: 0; left: 0; right: 0; bottom: 0; overflow-y: auto; - 若必须用局部滚动容器,则检测目标元素而非
window:el.scrollTop + el.clientHeight >= el.scrollHeight - 100,并监听该元素的scroll事件 - iOS 还需加
-webkit-overflow-scrolling: touch启用原生弹性滚动,否则scroll事件可能不触发
最易忽略的一点:很多团队只在开发机上验证了 Chrome 桌面版,但上线后发现 iOS 用户永远触发不了加载——根本原因是没意识到滚动主体不是 window。










