<template>
<div class="box" @scroll="handleScroll">
<div :style="{ height: `${itemHeight * itemCount}px` }">
<div
v-for="(item, index) in renderList"
:key="index"
class="item"
:style="{ transform: `translateY(${offsetY}px)` }"
>
{{ item }}
</div>
</div>
</div>
</template>
<script setup>
import { computed, onMounted, ref } from "vue";
// 渲染item数量
const itemCount = 10_0000;
// 每个item的高度
const itemHeight = 32;
// 创建数据列表
const list = computed(() =>
Array.from({ length: itemCount }).map((c, i) => `某某数据${i + 1}`)
);
// 要渲染的list
const renderList = ref([]);
let start = 0;
// 偏移量
let offsetY = 0;
// 可视区域渲染的数量
let volume = 0;
// 滚动事件
const handleScroll = (e) => {
const scrollTop = e.target.scrollTop;
let currentStart = Math.floor(scrollTop / itemHeight);
if (start != currentStart) {
offsetY = scrollTop - (scrollTop % itemHeight);
start = currentStart;
renderList.value = list.value.slice(start, start + volume);
}
};
onMounted(() => {
volume = Math.ceil(300 / itemHeight) + 5;
renderList.value = list.value.slice(start, volume);
});
</script>
<style>
.box {
height: 300px;
width: 1000px;
margin: 100px auto;
border: 1px solid #888;
max-height: 300px;
overflow-y: auto;
}
.item {
height: 32px;
line-height: 32px;
padding: 0 12px;
transform: background-color 0.3s;
}
.item:hover {
background-color: skyblue;
}
</style>
vue3虚拟列表
最新推荐文章于 2024-06-07 10:59:21 发布