虚拟列表

进行大量列表的渲染时,过多的DOM元素需要消耗大量的性能,这时使用虚拟列表是个不错的选择!

什么是虚拟列表

虚拟列表其实是按需显示的一种实现,即只对可见区域进行渲染,对非可见区域中的数据不渲染或部分渲染的技术,从而达到极高的渲染性能。

假设有1万条记录需要同时渲染,我们屏幕的可见区域的高度为500px,而列表项的高度为50px,则此时我们在屏幕中最多只能看到10个列表项。

假设滚动发生,滚动条距顶部的位置为150px,则我们可得知在可见区域内的列表项为第4项第13项

img

实现

1
2
3
4
5
6
7
8
9
<div class="infinite-list-container">
<div class="infinite-list-phantom"></div>
<div class="infinite-list">
<!-- item-1 -->
<!-- item-2 -->
<!-- ...... -->
<!-- item-n -->
</div>
</div>
  1. 设置占位容器,用于撑起滚动条。infinite-list-phantom 为容器内的占位。
  2. 渲染屏幕内能够容纳的元素,根据索引对总数据进行截取。infinite-list 为列表项的渲染区域

img

  1. 计算当前可视区域起始数据索引****startIndex
  2. 计算当前可视区域结束数据索引****endIndex
  3. 计算当前可视区域的数据,并渲染到页面中
  4. 计算startIndex对应的数据在整个列表中的偏移位置startOffset并设置到列表上
  • 列表总高度listHeight = listData.length * itemSize
  • 可显示的列表项数visibleCount = Math.ceil(screenHeight / itemSize),数量为(500 / 50) + 1,多一个偏移项
  • 数据的起始索引startIndex = Math.floor(scrollTop / itemSize)
  • 数据的结束索引endIndex = startIndex + visibleCount,最大为数据总长度。
  • 列表显示数据为visibleData = listData.slice(startIndex,endIndex)

当滚动后,由于渲染区域相对于可视区域已经发生了偏移,此时我需要获取一个偏移量startOffset,通过样式控制将渲染区域偏移至可视区域中。

  • 偏移量startOffset = scrollTop - (scrollTop % itemSize);不超过一个,不用偏移,超过一个,偏移超过的floor值。

img

监听容器内的滚动事件,不断的对上面的数据进行重新赋值即可。

以上思路仅适用于固定高度列表。