
<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";
const itemCount = 10_0000;
const itemHeight = 32;
const list = computed(() =>
Array.from({ length: itemCount }).map((c, i) => `某某数据${i + 1}`)
);
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>