处理海量数据通常就两种方案:
一、时间分片
时间分片主要解决,初次加载,一次性渲染大量数据造成的卡顿现象。浏览器执 js 速度要比渲染 DOM 速度快的多。
时间分片,并没有本质减少浏览器的工作量,而是把一次性任务分割开来,给用户一种流畅的体验效果
二、长列表渲染
虚拟列表是一种长列表的解决方案,
滑动加载是 M 端和 PC 端一种常见的数据请求加载场景,这种数据交互有一个问题就是,如果没经过处理,加载完成后数据展示的元素,都显示在页面上,如果伴随着数据量越来越大,会使页面中的 DOM 元素越来越多,即便是像 React 可以良好运用 diff 来复用老节点,但也不能保证大量的 diff 带来的性能开销。
所以虚拟列表的出现,就是解决大量 DOM 存在,带来的性能问题。
何为虚拟列表,就是在长列表滚动过程中,只有视图区域显示的是真实 DOM ,滚动过程中,不断截取视图的有效区域,让人视觉上感觉列表是在滚动。达到无限滚动的效果。
虚拟列表划分可以分为三个区域:视图区 + 缓冲区 + 虚拟区。
- 视图区:视图区就是能够直观看到的列表区,此时的元素都是真实的 DOM 元素。
- 缓冲区:缓冲区是为了防止用户上滑或者下滑过程中,出现白屏等效果。(缓冲区和视图区为渲染真实的 DOM )
- 虚拟区:对于用户看不见的区域(除了缓冲区),剩下的区域,不需要渲染真实的 DOM 元素。虚拟列表就是通过这个方式来减少页面上 DOM 元素的数量。
具体实现思路。
- 通过 useRef 获取元素,缓存变量。
- useEffect 初始化计算容器的高度。截取初始化列表长度。这里需要 div 占位,撑起滚动条。
- 通过监听滚动容器的 onScroll 事件,根据 scrollTop 来计算渲染区域向上偏移量, 这里需要注意的是,当用户向下滑动的时候,为了渲染区域,能在可视区域内,可视区域要向上滚动;当用户向上滑动的时候,可视区域要向下滚动。
- 通过重新计算 end 和 start 来重新渲染列表。