分片渲染通过requestIdleCallback或requestAnimationFrame将大批量DOM插入拆分为小块,在浏览器空闲时或每帧间隙执行,配合DocumentFragment批量插入以避免重复重排;兼容性方案用setTimeout或Promise.resolve(),并禁用innerHTML和循环appendChild。

直接一次性插入成千上万条数据到 DOM,主线程会被长时间占用,用户会明显感到卡顿、滚动掉帧、按钮无响应。分片渲染不是“减少数据”,而是把渲染动作切成小块,在浏览器空闲时或每帧间隙中执行,让出控制权给渲染和交互。
用 requestIdleCallback 拆分并调度渲染
这是最符合浏览器调度逻辑的方式:它只在主线程空闲时运行,自动避开用户输入、动画等高优任务。
- 每批处理 20–50 条数据,避免单次执行超 50ms(长任务阈值)
- 每次执行后检查 deadline.timeRemaining() > 1,有剩余时间就继续,否则退出,等待下一次空闲
- 配合 DocumentFragment 批量插入,避免反复触发 layout 和 paint
用 requestAnimationFrame 控制帧节奏
适合对渲染时机要求更明确的场景,比如希望每帧只做一批,确保与屏幕刷新率同步(约 60fps)。
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
- 每批渲染后调用 requestAnimationFrame,让浏览器在下一帧开始时执行下一批
- 比 setTimeout(0) 更精准,不会因事件循环拥堵而延迟
- 仍需搭配 DocumentFragment,否则单批内多次 appendChild 仍会引发多次重排
兼容性兜底:setTimeout 或 Promise.resolve()
当目标环境不支持 requestIdleCallback(如旧版 Safari)时,可用微任务或宏任务主动让出主线程。
- 每渲染 50 条后调用 setTimeout(() => {}, 0) 或 await Promise.resolve()
- 注意不要拆得太碎(例如每条都加 setTimeout),否则任务调度开销反而拖慢整体速度
- 适用于单页 500–2000 条中等规模数据,兼顾性能与兼容性
关键细节不能漏
光拆分任务还不够,DOM 操作本身也是性能热点:
- 不用 innerHTML 拼接:字符串拼接再赋值会触发完整 HTML 解析,且无法复用已有元素
- 不用循环中逐个 appendChild:每次都会触发样式计算和布局,1000 次 = 1000 次重排
- 务必用 DocumentFragment 中转:它不挂载在真实 DOM 树上,添加子节点完全不触发渲染,最后一次性插入即可
- 避免在分片过程中读取 offsetHeight、scrollTop 等触发强制同步布局的属性










