微信小程序虚拟列表

时间:2024-04-16 08:15:46

 

 

为啥使用长列表

需要展示长列表,无限下拉都会一直显示出更多的数据。但是当一个页面展示的DOM节点过多的时候,会造成小程序页面的卡顿,点击反应迟钝,严重的会直接白屏。

原因有几点

  • 列表数据很大,不断获取下一屏的数据,setData的数据越来越多的时候耗时高
  • 渲染DOM 结构多,每次 setData 都需要创建新的虚拟- 树、和旧树 diff 操作耗时都比较高
  • DOM 结构多,占用的内存高,造成页面被系统回收的概率变大,会白屏

首先想到的是使用二维数组

  • 首先开始是每次渲染数据都重新进行push,然后setData赋值,但是这样做的效果是数据过多时就会出现卡顿,白屏
  • 于是着手把数据变成二位数组,setData时只对当前索引赋值这样的好处是可以减轻setData数据

本以为这样的话可以解决但是试了试数据过大时仍然卡顿,dom渲染还是很多,于是只渲染在当前屏幕的,其他位置用空标签占位

解决方案:

方案1
<block >
    <block 
      wx:for="{{infoList}}"
      wx:for-item="infoItemList"
      wx:for-index="pageNum"
      wx:key="pageNum">
      <info-item
        custom-class="info-item"
        useCustomSlot="{{false}}"
        wx:for="{{infoItemList}}"
        data-index="{{index}}"
        data-page="{{pageNum}}"
        wx:key="id"
        info="{{item}}"
      >
      </info-item>
    </block>
  </block>

 

  • 有两层循环,第一层循环最外层的(二维数组索引),第二层循环每屏数据info-item是封装的每个item展示数据
  • 现在做的就是在这上面优化让在视图内的显示数据,不在试图内的让view标签占位
  • 接着我们存储每屏高度,然后记录滚动距离,获取现在应该渲染那几屏
  • 滚动距离

    根据这个滚动距离以及每一屏的高度,来计算当前应该渲染哪一屏的数据。这个需要怎么去算?其实很简单,循环去遍历每屏高度,用第一屏的高度 与滚动高度 + 当前屏幕的高度this.windowHeight做比较,如果滚动高度比较小,则用第一屏累加第二屏的高度,一直到第一屏幕累计高度 > 滚动高度 + this.windowHeight 就是当前应该渲染的屏幕。

方案2:
  • 利用observeAPI 在每一屏渲染完成后,监听当前这一屏是否在可视区域内,如果在就给它赋值正常的数组,
    wx.createIntersectionObserver
    
  •