朱丽叶

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

vue 实现虚拟列表


// 调用组件
<List :arr="dataList">
  <template #default="{item}">
    {{item * 3}}
  </template>
</List>


// 虚拟列表组件
<template>
  <div class=''>
    <!-- 给用户看到的20个元素的容器 -->
    <div class="view_port" ref="viewPortRef" @scroll="changeScroll">
      <!-- 为了撑开容器 -->
      <div class="scroll_bar" ref="scrollBarRef"></div>
      <!-- 虚拟的列表 -->
      <div class="list" :style="{ transform: `translate(0, ${offsetTop}px)` }">
        <div :style="{ 'height': size + 'px' }" v-for="(item, index) in itemsList" :key="index">
          <slot :item="item">{{item}}</slot>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang='ts'>
import { withDefaults, defineProps, ref, onMounted, computed } from "vue";

const props = withDefaults(defineProps<{
  arr: Array<number>, // 需要滚动的数据
  remain?: number, // 每个元素的高度
  size?: number // 视口展示元素的数量
}>(), {
  remain: 20,
  size: 20
})

const viewPortRef = ref<HTMLElement>();
const scrollBarRef = ref<HTMLElement>();

const initPage = () => {
  // 设置视口的高度
  viewPortRef.value!.style.height = props.remain * props.size + "px";
  // 设置整个滚动条的高度
  scrollBarRef.value!.style.height = props.arr.length * props.size + 'px';
}

const startIndex = ref(0);
const endIndex = ref(props.size);
const offsetTop = ref(0);

// 用于获取真实得到的列表
const itemsList = computed(() => props.arr.slice(startIndex.value, endIndex.value))

// 监听页面的滚动
const changeScroll = () => {
  // 计算向上卷入的元素的开始下标,乡下取整
  startIndex.value = Math.floor(viewPortRef.value!.scrollTop / props.size);
  // 计算截取的元素结束下标
  endIndex.value = startIndex.value + props.size;

  // 可视高度向下偏移的数量
  offsetTop.value = startIndex.value * props.size
}


onMounted(() => {
  initPage();

})

</script>
<style scoped>
.view_port {
  overflow-y: scroll;
  position: relative;
}

.list {
  position: absolute;
  top: 0;
  left: 0;
}
</style>

posted on   朱丽叶  阅读(342)  评论(1编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示