直接监听 scroll 易卡顿因触发频率过高导致重排重绘,应改用 IntersectionObserver 实现触底加载,配合 cursor 分页与 AbortController 避免状态混乱。
scroll 容易卡顿?因为原生 scroll 事件触发频率极高(每毫秒都可能触发),若在回调里直接调用 fetch 或操作 DOM,浏览器会频繁重
排重绘,导致掉帧。尤其在低端设备或列表项含图片/复杂样式时,scrollTop 检查 + appendChild 组合极易引发 Layout Thrashing。
关键不是“要不要监听”,而是“什么时候响应”。必须加节流或采用更稳定的检测方式:
IntersectionObserver 替代 scroll + 手动计算 —— 它由浏览器原生调度,不阻塞主线程scroll,至少用 requestIdleCallback 或 setTimeout(..., 0) 延迟到空闲期执行加载逻辑document.documentElement.scrollHeight 和 scrollTop,这些是强制同步布局的“脏读”IntersectionObserver 实现可靠触底加载?它不依赖滚动位置数值,而是观察一个“占位元素”(sentinel)是否进入视口。只要它一出现,就说明该加载下一页了。这种方式对虚拟滚动、动态高度、甚至 CSS transform 位移都兼容。
注意三个易错点:
rootMargin 要设为类似 "0px 0px 200px 0px",提前 200px 触发,避免用户已看到空白才开始请求observe()
unobserve(sentinel),防止重复触发;新数据追加后,再 observe() 新的 sentinelconst observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && !loading) {
observer.unobserve(sentinel);
loadMore().finally(() => observer.observe(sentinel));
}
},
{ rootMargin: "0px 0px 200px 0px" }
);
observer.observe(sentinel);
渲染 1 万条 ,哪怕内容为空,浏览器也要维护上万个 Layout Object。此时任何优化 JS 逻辑都是隔靴搔痒。必须做 DOM 节点复用(即“窗口化”)。
核心策略是只保留可视区域 ±1~2 屏的 DOM 节点,其余用 height 占位:
getBoundingClientRect() 或 scrollTop + 容器高度算出当前应显示的起始索引transform: translateY() 定位,避免影响文档流DocumentFragment 批量更新,减少重排次数如果业务允许,直接用成熟库如 react-window 或 vue-virtual-scroller,它们已处理好滚动精度、键盘导航、动态高度等边缘 case。
前端无限滚动常误用 page=1, page=2... 这类偏移式分页,导致翻页时插入新数据后,用户滚动位置突变、重复加载、或漏数据。正确做法是用游标(cursor)分页:
cursor(例如最后一条记录的 id 或 created_at 时间戳)cursor,下次请求带过去,不依赖页码或 offset
另外,AbortController 必须用上:每次新请求前 abort 上一个未完成的请求,否则旧请求返回后覆盖新数据,UI 就会“倒退”。
# css
# vue
# react
# javascript
# java
# js
# 前端
# 浏览器
# app
# 后端
# win
# 并发请求
# 重绘
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
Mac系统更新下载慢或失败怎么办_解决macOS升级问题【方法】
Win10如何备份驱动程序_Win10驱动备份步骤【攻略】
Windows蓝屏错误0x00000018怎么处理_驱动初始化错误解决
Win11怎么更改任务栏颜色_Windows11个性化重音色设置
Win10怎样卸载自带Edge_Win10卸载Edge浏览器步骤【教程】
Win11怎么开启自动HDR画质_Windows11显示设置HDR选项
VSC怎样在Linux运行PHP_Ubuntu系统配置步骤【操作】
Python正则表达式实战_模式匹配说明【教程】
PHP中require语句后直接调用返回对象方法的语法解析
XML的“混合内容”是什么 怎么用DTD或XSD定义
Windows10蓝屏SYSTEM_SERVICE_EXCEPTION_Win10驱动冲突排查
Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤
Drupal 中 HTML 链接被重复转义导致渲染异常的解决方案
Mac的访达(Finder)怎么用_Mac文件管理入门教程【详解】
Windows如何拦截腾讯视频广告_Windows拦截腾讯视频广告方法【方法】
如何使用Golang捕获测试日志_Golang testing日志记录方法
php下载安装后swoole扩展怎么安装_异步框架支持【汇总】
MySQL 中使用 IF 和 CASE 实现查询字段条件化显示
如何在 Windows 11 中使用 AlomWare 工具箱
如何在Golang中操作嵌套切片指针_Golang多维slice修改
如何在Golang中定义接口_抽象方法和多态实现
php订单日志怎么导出excel_php导出订单日志到表格教程【教程】
c++的static关键字有什么用 静态变量和静态函数的应用场景【教程】
手机php文件怎么变成mp4_安卓苹果打开php转mp4方法【教程】
php转exe用什么工具打包快_高效打包软件推荐【汇总】
Win11声音忽大忽小怎么办 Win11音频增强功能关闭教程【修复】
php在Linux怎么部署_LNMP环境搭建PHP服务的详细指南【指南】
Python函数接口文档化_自动化说明【指导】
PythonFastAPI项目实战教程_API接口与异步处理实践
Win11麦克风没声音怎么设置_Win11麦克风权限及驱动修复【教程】
Win11怎么开启窗口对齐助手_Windows11系统多任务处理设置
WindowsUSB驱动安装异常怎么办_USB驱动重建与恢复教程
Windows怎样关闭Edge新标签页广告_Windows关闭Edge新标签页设置【步骤】
为什么Go建议使用error接口作为错误返回_Go Error接口设计原因说明
c++如何实现多态性_c++ 虚函数表原理与动态绑定机制【教程】
php串口通信波特率怎么选_根据硬件手册设置正确波特率【方法】
如何使用Golang构建简易投票统计功能_Golang投票数据汇总与展示示例
如何在 VS Code 中正确配置并使用 NumPy
如何在Golang中验证模块完整性_Golanggo.sum校验与安全实践
如何在Golang中实现邮件发送功能_Golang SMTP发送与错误处理示例
Windows电脑如何进入安全模式?(多种按键方法)
c++怎么实现大文件的分块读写_c++ 文件指针seekp与seekg偏移控制【方法】
Win10怎样清理C盘Steam游戏缓存_Win10清理Steam游戏缓存步骤【步骤】
Python技术债务管理_长期维护解析【教程】
Windows10如何更改系统字体大小_Win10辅助功能文本缩放设置
如何在Golang中实现WebSocket广播_使用Channel和协程分发消息
php命令行怎么运行_通过CLI模式执行PHP脚本的步骤【说明】
Win11怎么自动隐藏任务栏_Win11全屏显示设置【美化】
Python多线程使用规范_线程安全解析【教程】
如何使用Golang sync.Map实现并发安全map_避免锁竞争
2025-12-31
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。