长列表懒加载

1,051 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

懒加载

经常会遇到这样的问题,如果后端给我们20000条数据,我们要怎么加载它,直接全部渲染到dom上?不,这样不行,这样我的页面会卡死,性能影响太严重,我们可以只加载此时的视图范围内的数据

实现

  • 首先需要一个数组,里面放20000条数据
  • 每次只加载视图范围内的数据,我们就需要一个开始的下标,一个结束的下标,用来确认此时应该展示的数据范围
  • 还需要一个值用来确认此时的滚动的top值,确定此时的试图在哪里

一个节点,用来展示滚动条,里面放一个撑起滚动条的节点,他的高度为数组的长度 * 25(25为自定义), 另一个节点放需要渲染的dom

HTML结构如下

<div class="listContext" @scroll="listScroll">
    <div ref="scrollHeight"></div>
    <div class="warp">
      <div>
        //需要熏染的节点在这里
      </div>
    </div>
</div>

CSS
.listContext {
  height: 200px;
  overflow: scroll;
  position: relative;
}
.warp {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

逻辑

  • 当我们滚动的时候,触发滚动事件,然后拿到滚动到上面的top
  • 确定此时的top所对应的开始的下标是多少:stateIndex = ScrollTop / 25(渲染节点的高度)
  • endIndex = stateIndex + 此时试图需要渲染的数量
  • 这样我们就可以截取数组,拿到需要渲染的数组,通过v-for,渲染到dom中
  • 但是还需要把此时的warp向下移动,移动stateIndex * 25 的高度,因为我们向下滚动了这么多,所以需要移动

逻辑实现

创建10000条数据

for (let i = 0; i < 1000; i++) {
  listArray.push(i);
}

滚动事件,确认stateIndex,endIndex,scrollOffset

const listScroll = (e) => {
  stateIndex.value = Math.ceil(e.target.scrollTop / 25);
  endIndex.value = 200 / 25 + stateIndex.value;
  scrollOffset.value = stateIndex.value * 25;
};

监听stateIndex,endIndex

watchEffect(() => {
  showArray.value = listArray.slice(stateIndex.value, endIndex.value);
})
onMounted(() => {
  //确认滚动条高度
  scrollHeight.value.style.height = listArray.length * 25 + "px";
});

HTML

<div class="listContext" @scroll="listScroll">
    <div ref="scrollHeight"></div>
    <div :style="{ transform: `translateY(${scrollOffset}px)` }" class="warp">
      <div v-for="item in showArray" :key="item" class="item">
        {{ item }}
      </div>
    </div>
</div>

此时的就可以展示我们需要展示的内容了

ChromeCore_CtrcfVWMAI.gif

我们可以看到,一直都是只渲染8条数据,极大的提高了性能

结束

今天面试了两家,感觉自己又行了,加油哇!