vue3实现一个简易的虚拟列表(附带源码)

介绍

虚拟列表主要是解决当列表数量较多时(比如上十万条数据、百万万条数据),页面内引入大量的 DOM 元素导致页面卡顿的情况,当然对于列表数量没达到足够的量级(主要根据自己的业务来衡量)但是想提高首屏加载速度时,也可以选择按需加载列表,类似于图片的懒加载,并非一次性渲染全部列表,而在滚动到页面底部的时候,再去加载剩余的数据。但是对于业务需求就是一次性返回所有数据的时候选择用虚拟列表去加载更合适。

那么接下来我开始介绍虚拟列表的实现:

思路就是用vue的for循环渲染列表,自己手动加一个滚动条,然后通过监听scroll,算出应该显示到第几个,加载对应区域的数据,列表项的dom数量始终不变。

我们这里也不废话直接代码演示

<template>
  <div
    :style="{ height: `${data.contentHeight}px` }"
    ref="contentBox"
    class="content_box"
    @scroll="scroll"
  >
    <!--这层div是为了把高度撑开,让滚动条出现,height值为所有数据总高-->
    <div
      :style="{
        height: `${data.itemHeight * data.listAll.length}px`,
        position: 'relative',
      }"
    >
      <!--可视区域里所有数据的渲染区域-->
      <div :style="{ position: 'absolute', top: `${data.top}px` }">
        <!--单条数据渲染区域-->
        <div v-for="(item, index) in data.showList" :key="index" class="item">
          {{ item }}
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {
  ref,
  reactive,
  toRefs,
  onBeforeMount,
  onMounted,
  watchEffect,
  computed,
  nextTick,
} from "vue";

const data = reactive({
  listAll: [], //所有数据
  showList: [],
  contentHeight: 500, //可视区域高度
  itemHeight: 30, //每条数据所占高度
  showNum: 0, //可是区域显示的最大条数
  top: 0, //偏移量
  scrollTop: 0, //卷起的高度
  startIndex: 0, //可视区域第一条数据的索引
  endIndex: 0, //可视区域最后一条数据后面那条数据的的索引,因为后面要用slice(start,end)方法取需要的数据,但是slice规定end对应数据不包含在里面
});
const contentBox = ref();
//构造10万条数据
const getList = () => {
  for (let i = 0; i < 100000; i++) {
    data.listAll.push(`我是第${i}条数据呀`);
  }
};
//计算可视区域数据
const getShowList = () => {
  data.showNum = Math.ceil(data.contentHeight / data.itemHeight); //可视区域最多出现的数据条数,值是小数的话往上取整,因为极端情况是第一条和最后一条都只显示一部分
  data.startIndex = Math.floor(data.scrollTop / data.itemHeight); //可视区域第一条数据的索引
  data.endIndex = data.startIndex + data.showNum; //可视区域最后一条数据的后面那条数据的索引
  data.showList = data.listAll.slice(data.startIndex, data.endIndex); //可视区域显示的数据,即最后要渲染的数据。
  const offsetY = data.scrollTop - (data.scrollTop % data.itemHeight); //在这需要获得一个可以被itemHeight整除的数来作为item的偏移量,这样随机滑动时第一条数据都是完整显示的
  data.top = offsetY;
};
//监听滚动事件,实时计算scrollTop
const scroll = () => {
  data.scrollTop = contentBox.value.scrollTop; //element.scrollTop方法可以获取到卷起的高度
  getShowList();
};
onMounted(() => {
  // 等待dom渲染完毕
  getList();
  scroll();
});
</script>
<style scoped >
.content_box {
  overflow: auto; /*只有这行代码写了,内容超出高度才会出现滚动条*/
  width: 700px;
  border: 1px solid red;
}
/*每条数据的样式*/
.item {
  height: 30px;
  padding: 5px;
  color: #666;
  box-sizing: border-box;
}

</style>


注:作者这里是demo 没有设置缓冲参数

有些情况行高是不确定的,最好的办法是定义一个预测高度,等元素渲染出来马上把该元素高度缓存,等到下次该元素出来的话就用这个高度初始化,然后该元素到了可视区再次缓存高度(解决表格宽度自适应)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3提供了一个新的组件API,使得构建虚拟列表变得更加容易。下面是一个简单的实现示例: 1. 安装依赖: ```bash npm install vue@next npm install vue3-virtual-scroll-list ``` 2. 在组件中使用虚拟列表: ```vue <template> <virtual-scroll-list :size="50" :remain="20" :data-key="'id'" :data-sources="items" @scroll="handleScroll" > <template v-slot="{ data }"> <div v-for="item in data" :key="item.id">{{ item.text }}</div> </template> </virtual-scroll-list> </template> <script> import { ref } from 'vue' import VirtualScrollList from 'vue3-virtual-scroll-list' export default { components: { VirtualScrollList, }, setup() { const items = ref([]) // 初始化数据 for (let i = 0; i < 10000; i++) { items.value.push({ id: i, text: `Item ${i}`, }) } const handleScroll = (scrollTop) => { // 处理滚动事件 console.log(scrollTop) } return { items, handleScroll, } }, } </script> ``` 在这个示例中,我们使用 `vue3-virtual-scroll-list` 组件来实现虚拟列表。这个组件需要传入一些参数,包括: - `size`:每个项的高度 - `remain`:上下额外渲染项的数量 - `data-key`:数据中每个项的唯一标识符 - `data-sources`:数据源 - `scroll`:滚动事件的回调函数 在模板中,我们使用插槽来渲染每个项。同时,组件还会将已经渲染的项缓存起来,以提高性能。 在 `setup` 函数中,我们初始化了一个 `items` 的响应式变量,并将它传入 `data-sources` 中。我们还定义了一个 `handleScroll` 函数来处理滚动事件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值