代码:
<template>
<div class="test">
<div ref="testRef" class="h-96 overflow-y-scroll">
<ul :style="{ transform: `translateY(${translateY})` }">
<li
class="testBox h-16 flex items-center border-b-2 text-2xl"
v-for="item in listData"
:key="item.id"
>
{{ item.title }}
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
type testInfo = {
id: number
title: string
}
const data = ref<testInfo[]>([])
for (let i = 1; i < 99; i++) {
data.value.push({
id: i,
title: `标题${i}号`
})
}
const testRef = ref<any>()
const start = ref<number>(0)
const translateY = ref<number | string>(0)
const listData = computed(() => {
return data.value.slice(start.value, start.value + 7)
})
onMounted(() => {
testRef.value.addEventListener('scroll', (e: any) => {
const { scrollTop } = e.target
start.value = Math.floor(scrollTop / 64)
translateY.value = scrollTop + 'px'
})
})
</script>
解析:
- 创建一个固定高度的父盒子,以及固定高度的列表
- 将父盒子设置为溢出滚动,监听父盒子滚动的高度,计算出需要渲染的数据列表的初始索引值,结束索引值设置为初始索引值+1,+1是为了避免渲染时出现空白。
- 将ul向上偏移,偏移量等于滚动高度,使ul和父盒子始终高度对齐。