324 字
2 分钟
vue虚拟列表
github上的vue虚拟列表:
vue-virtual-scroller
以下是简易demo:
<template>
<div ref="list" class="v-scroll" @scroll="scrollEvent">
<div class="infinite-list" :style="{ height: listHeight + 'px' }"></div>
<div class="scroll-list" :style="{ transform: getTransform }">
<p
ref="items"
class="scroll-item"
v-for="item in visibleData"
:key="item.id"
:style="{ height: itemHeight + 'px', lineHeight: itemHeight + 'px' }"
>
{{ item.msg }}
</p>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, nextTick } from "vue";
let listdata = [];
for (let i = 1; i <= 10000; i++) {
listdata.push({
id: i,
msg: i + ":" + Math.floor(Math.random() * 10000),
});
}
const start = ref(0);
const end = ref(0);
const startOffset = ref(0);
const itemHeight = ref(60);
const listHeight = ref(listdata.length * itemHeight.value);
const list = ref(null); //获取节点
//可视区域高度
const screenHeight = 600;
//可显示的列表项数
const visibleCount = Math.ceil(screenHeight / itemHeight.value); //多放3个
onMounted(() => {
start.value = 0;
end.value = start.value + visibleCount;
});
//偏移量对应的style
const getTransform = computed(() => {
return `translate3d(0,${startOffset.value}px,0)`;
});
//获取真实显示列表数据
const visibleData = computed(() => {
return listdata.slice(start.value, Math.min(end.value, listdata.length));
});
function scrollEvent() {
//当前滚动位置
let scrollTop = list.value.scrollTop;
//此时的开始索引
start.value = Math.floor(scrollTop / itemHeight.value);
//此时的结束索引
end.value = start.value + visibleCount;
//此时的偏移量
startOffset.value = scrollTop - (scrollTop % itemHeight.value);
}
</script>
<style scoped>
.v-scroll {
height: 600px;
width: 400px;
border: 3px solid #000;
overflow: auto;
position: relative;
-webkit-overflow-scrolling: touch;
color: #fff;
}
.infinite-list {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
}
.scroll-list {
left: 0;
right: 0;
top: 0;
position: absolute;
text-align: center;
}
.scroll-item {
box-sizing: border-box;
border-bottom: 1px solid #999;
}
</style>