虚拟列表——一次性请求大量数据优化

情景:

后端一次性传了10000条数据(假设存在),需要前端展示。若真的一次性全部展示出来性能消耗大,一万条数据不明显,十万条呢,肯定会导致页面卡顿的。

实现思路:
使用虚拟列表实现,其实和分页类似,就是前端自己裁剪数据,一次性值展现固定量的数据。如果使用element-plus可以直接使用他们的虚拟化表格,这里就不过多展示了。
布局:三个div,大的容器,大的放滚动事件,里面放两个小的div,一个用来撑开容器,另一个作为可视区域。
步骤1:监听滚动事件,在里面获取scrollTop,计算开始位置,开始位置其实就是scrollTop/height。
步骤2:按长度切割数组,获取需要渲染的内容。
 
<script setup lang="ts">
import { computed, onMounted, reactive, ref } from "vue";
let start = ref(0),
  size = ref(10),
  height = ref(20),
  scrollTop = ref(0),
  totalList = reactive<string[]>([]);

const virtualListRef = ref(null);
onMounted(() => {
  for (let i = 0; i < 10000; i++) {
    totalList.push(`第${i}个`);
  }

  virtualListRef.value.style.height = height.value * size.value + "px";
});
// 需要渲染的数组
const renderList = computed(() => {
  return totalList.slice(start.value, start.value + size.value);
});

const handleScroll = () => {
  scrollTop.value = virtualListRef.value.scrollTop;
  // 开始的位置等于滚动的距离除高度
  start.value = scrollTop.value / height.value;
};
</script>

HTML

<template>
  <div class="wrapper">
    <div id="virtualList" ref="virtualListRef" @scroll="handleScroll">
      <!-- 空白div -->
      <div :style="{ height: totalList.length * height + 'px' }"></div>
      <!-- 可视区域 -->
      <div class="container" :style="{ top: scrollTop + 'px' }">
        <div
          class="item"
          v-for="item in renderList"
          :style="{ height: height + 'px' }"
        >
          {{ item }}
        </div>
      </div>
    </div>
  </div>
</template>

CSS

<style scoped>
#virtualList {
  position: relative;
  overflow: auto;
  width: 200px;
  height:200px;
  border: 1px green solid;
}
.container {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
}
</style>

 效果图

 

posted @ 2023-06-09 15:14  Sofiaღ  阅读(165)  评论(0编辑  收藏  举报