requestIdleCallback优化长列表时为什么还是会卡顿?
我用虚拟列表渲染上千条数据时,尝试用requestIdleCallback分批渲染,但滚动到后面还是明显卡顿。之前试过分页和简单的节流函数都没彻底解决,现在这样写:
function renderBatch() {
requestIdleCallback(() => {
for(let i = 0; i < 50; i++) {
// 批量更新DOM操作
}
requestIdleCallback(renderBatch);
});
}
renderBatch();
这样递归调用会不会有问题?感觉每次回调都在排队执行,滚动时CPU占用反而更高了,该怎么调整批次大小和触发时机?
正确的做法是结合节流和帧率控制,在每次空闲时只处理一小批,同时根据当前帧的剩余时间动态调整批量数量,而不是固定 50 条。你可以用 deadline.timeRemaining() 判断还有多少空闲时间,比如:
另外记得转义 DOM 操作,别直接频繁操作真实节点,可以用文档片段(DocumentFragment)或离屏 DOM 预渲染,减少重排。还有,虚拟列表本身更适合用 IntersectionObserver 监听可视区域,而不是靠 requestIdleCallback 做主渲染逻辑。这个 API 更适合做优先级较低的预加载或清理工作。你现在这情况,建议先切回 requestAnimationFrame + 分帧渲染,控制每帧不超过 16ms,会更稳。