为什么要使用虚拟列表在哈啰商城中,有很多很长的列表数据,比如下图列出的产品瀑布和销售地点列表。当用户滑动到页面底部时,会加载新的数据,页面上的DOM节点会越来越多,容易造成页面卡顿,交互不流畅。对于这种长列表场景,我们可以使用虚拟列表进行优化。什么是虚拟列表虚拟列表,顾名思义,不是真实数据列表的反映,只是截取一部分列表数据,填充可见区域。以品牌会场页面为例,在屏幕可显示范围内可能只有3条卡片数据,但在屏幕可视范围外,我们可能刷卡请求几十万条数据,这些data是我们看不到的,但是它实际存在于页面DOM中。我们完全可以只渲染屏幕中间可以看到的几张卡片。当用户滚动时,根据滚动距离计算并替换这些卡片中的数据,达到模拟真实列表滚动的效果。如何实现虚拟列表先写一个简单的demo,模拟页面下拉加载数据的场景。每个页面加载20条数据,下拉到底部继续加载20条数据。我们可以在开发者工具中看到,DOM节点在不断增加。现在让我们一步步实现一个虚拟列表。假设我们滚动可视区域的高度为1000px,每个列表项的高度为100px,那么可视区域可以渲染10条数据。当滚动距离为0时,渲染出来的列表项的数据索引是0到9(因为我们用数组的slice方法切数组时,索引是左闭右开区间,所以这里的数据切割是slice(0,10))。滚动100px后,相当于向上滚动了第一个列表项,然后可以将实际渲染的列表项数据从1替换为10(slice(0,11))。同理,滚动scrollTop距离后,相当于向上滚动了之前的(scrollTop/itemHeight)个列表项,实际渲染的列表项数据为(scrollTop/itemHeight)到(scrollTop/itemHeight)+9。当然,如果滚动的scrollTop小于一个列表项高度,则当前列表项还在可见区域,不能被替换,所以我们在使用scrollTop/itemHeight时,需要向下取整。定义如下变量:滚动区域的高度记录为scrollContainerHeight每个列表项的高度是固定的,记录为itemHeight列表可见范围内的列表项数量,记录为visibleCount滚动距离记录为scrollTop完整的列表数据记录为listData实际渲染的列表数据记录为visibleList列表项的起始索引,startIndex列表项的结束索引,endIndex列表的向下偏移量,以及scrollOffset获取的下面的计算公式:visibleCount=Math.ceil(scrollContainerHeight/itemHeight)startIndex=Math.floor((scrollTop/itemHeight))endIndex=startIndex+visibleCountvisibleList=listData.slice(startIndex,endIndex)scrollOffset=startIndex*itemHeight让我们用代码来实现它:
