当后端一次性返回10w条数据,前端页面如果一次渲染的话,会有延迟,或者页面直接卡死,所以需要用到虚拟列表,每次加载可视区域内的数据,滚动页面的时候,更新数据。
废话不多说,直接上代码~
像这样,只更新可视区域的数据:
1691479026988.png
1、cell高度固定
<template>
<div class="base-layout">
<div ref="scrollRef" class="scroll-view" @scroll="handleScroll">
<div class="scroll-content" :style="{ height: contentHeight + 'px' }">
<div class="content-list" :style="{ paddingTop: topValue + 'px' }">
<p v-for="item in list" :key="item.id">{{ item.id }}</p>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, reactive, ref } from 'vue';
let allList = ref(<any>[]) // 所有数据
let contentHeight = ref(0) // 根据数据,计算scrolleViwe 的内部区域高度,为了显示滚动的可视区域
let topValue = ref(0) // 滚动条滚动距离顶部的高度
let startIndex = ref(0) // 要截取所有数据的起始下标
let visibleCount = ref(0) // 可视区域内的cell数量
const itemHeight = ref(30) // cell 的高度
const scrollRef = ref()
// 可视区域内要显示的数组
let list = computed(() => {
let arr = allList.value.slice(startIndex.value, startIndex.value + visibleCount.value)
return arr
})
onMounted(() => {
// scrollRef.value.offsetHeight: 获取可视窗口的高度
// 根据cell固定高度,计算可视区域内cell的数量
visibleCount.value = Math.ceil(scrollRef.value.offsetHeight / itemHeight.value)
getAllList()
})
function getAllList() {
for(let i = 1; i <= 100000; i++) {
allList.value.push({ id: i })
}
// 计算内容区域高度
contentHeight.value = allList.value.length * 30
}
function handleScroll(val: { target: { scrollTop: number; }; }) {
// 获取滚动条距离顶部的距离
topValue.value = val.target.scrollTop
// 计算起始下标
startIndex.value = Math.floor(topValue.value / itemHeight.value)
}
</script>
<style lang="scss" scoped>
.base-layout {
padding: 8px 20px;
.scroll-view {
background-color: papayawhip;
border: 1px solid orange;
box-sizing: border-box;
height: 300px;
width: 300px;
overflow-y: auto;
}
p {
height: 30px;
line-height: 30px;
margin: 0;
border-bottom: 1px solid gainsboro;
box-sizing: border-box;
}
}
</style>
网友评论