首先这个问题会有两个问题:
- 一次处理10w数据执行任务时间过长导致卡顿问题。
- 页面大量的DOM节点导致页面卡顿问题。
问题1解决方案:
用requestIdleCallback
或者setTimeout
实现一个分时函数
,在每一次空闲的时候去处理绘制这10w条数据。如果需要手写一个就如下:
/**
* 按批次执行任务
* @param {Array|Object} data 待执行任务的数据
* @param {Function} taskHandler 任务处理函数
*/
function performChunk(data, taskHandler) {
if (typeof data === 'number') {
data = {
length: data
}
}
if (data.length === 0) return;
let i = 0;
function _run() {
if (i >= data.length) return;
// 空闲时开启分片执行
requestIdleCallback((idle) => {
while(idle.timeRemaining() && i < data.length) {
taskHandler(data[i], i);
i++;
}
_run();
});
}
_run();
}
问题2解决方案:
如果是table就做一个前端分页渲染,如果是一个列表就使用虚拟列表方案。
这里可能会要求讲一下虚拟列表实现原理:
前端虚拟列表通过只渲染可视区域内的列表项,并动态调整和复用这些项的内容,从而在大量数据情况下优化性能和减少内存消耗。
实现步骤:
- 计算当前可见区域的起始数据索引:根据滚动的位置和其他因素来确定哪些数据项在当前可视区域内。
- 计算当前可见区域的结束数据索引:基于起始数据索引和一些特定的条件来计算结束数据索引。
- 渲染当前可见区域的数据:获取并渲染需要显示的数据项到页面上。
- 设置列表的偏移量:计算起始数据索引对应的偏移量并将其设置到列表上,确保滚动的准确性和连续性。
可能面试官又会问题,如何解决动态列高度问题:
- 对组件的属性 itemSize 进行扩展,使其支持传递不同的值,如数字、数组或函数。
- 测量列表项的高度并缓存,但这种方法会增加渲染的成本。
- 以预估的高度先行渲染,然后在适当的时候获取真实的高度并缓存起来,这是一种较为高效的实现方式。
插入10wDOM使用分时函数优化效果源代码
下载地址: 前端DEMO/分时函数.html