时间分片渲染长列表时卡顿怎么办?
我在用时间分片优化一个几千条数据的列表,每帧只渲染10条,但滚动时还是明显卡顿。是不是我的切片逻辑有问题?
我试过用 requestIdleCallback,也试过用 setTimeout 拆分任务,但效果都不太理想。下面是我目前的简化代码:
function renderInChunks(items, chunkSize = 10) {
let index = 0;
function renderChunk() {
const fragment = document.createDocumentFragment();
for (let i = 0; i < chunkSize && index < items.length; i++, index++) {
const el = document.createElement('div');
el.textContent = items[index];
fragment.appendChild(el);
}
container.appendChild(fragment);
if (index < items.length) {
requestIdleCallback(renderChunk);
}
}
renderChunk();
}
requestIdleCallback 这货在滚动时基本不会触发——浏览器正忙着处理滚动事件呢,哪有空闲时间给你?所以你设置的10条可能攒半天才能执行一次,体验反而更差。
改用 requestAnimationFrame 试试,把 chunkSize 加大:
把 chunkSize 调到 50-200 之间,requestIdleCallback 换成 requestAnimationFrame。这样每帧都有机会执行,调度开销也降下来了。
不过说真的,几千条数据与其这么搞,不如直接上虚拟列表——只渲染可视区域内的二三十条,滚动时动态计算偏移量替换内容。这是业界标准做法,性能比时间分片强得多。react-window 或者 vue-virtual-scroller 都有现成的轮子可以直接用。