feat: 定高item实现虚拟列表

master
LCJ-MinYa 10 months ago
parent 1fdbd0ee0d
commit 76a0215625

@ -64,6 +64,10 @@ const titleArr = [
key: 'viteProxy',
title: 'vite中设置代理转发',
},
{
key: 'virtualList',
title: 'item固定高度的虚拟列表实现',
},
];
// @/views/demo/**/*.vue

@ -0,0 +1,103 @@
<template>
<!-- 容器组件高度一定要是确定的高度不能由内容撑起 -->
<div
class="virtual-list-container"
ref="virtualListContainer"
@scroll="handleScroll($event)"
>
<!-- 绝对定位当父组件overflow:auto时占位组件可以撑起滚动条 -->
<div
class="placeholder"
:style="{ height: `${totalHeight}px` }"
></div>
<!-- 偏移量设置在每个item的父容器上面 -->
<div :style="{ transform: getTransform }">
<div
v-for="item in renderList"
:key="item.id"
class="item"
:style="{ height: `${itemHeight}px` }"
>
{{ item.text }}
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue';
/** 虚拟列表容器 */
const virtualListContainer = ref(null);
/** 虚拟列表容器高度 */
const containerHeight = ref(0);
/** 原始数据列表 */
const dataList = Array.from({ length: 1000 }, (_, i) => ({ id: i, text: `Item ${i}` }));
/** 虚拟列表单条item的高度 */
const itemHeight = 100;
/** 虚拟列表的总高度 */
const totalHeight = dataList.length * itemHeight;
const renderCount = computed(() => {
console.log('renderCount数量为', Math.ceil(containerHeight.value / itemHeight));
return Math.ceil(containerHeight.value / itemHeight);
});
/** 虚拟列表当前可见区域的起始索引 */
const start = ref(0);
/** 虚拟列表当前可见区域的结束索引 */
const end = computed(() => {
console.log('end索引为', start.value + renderCount.value);
return start.value + renderCount.value;
});
/** 虚拟列表当前可见区域的偏移量 */
const offset = ref(0);
const renderList = computed(() => {
console.log('renderList数据为', dataList.slice(start.value, end.value + 1));
return dataList.slice(start.value, end.value + 1);
});
const handleScroll = (e) => {
const scrollTop = e.target.scrollTop;
start.value = Math.floor(scrollTop / itemHeight);
offset.value = scrollTop - (scrollTop % itemHeight);
};
const getTransform = computed(() => {
return `translate3d(0, ${offset.value}px, 0)`;
});
onMounted(() => {
containerHeight.value = virtualListContainer.value.clientHeight;
console.log('containerHeight容器高度为', containerHeight.value);
});
</script>
<style lang="scss" scoped>
.virtual-list-container {
width: 100%;
height: calc(100vh - 81px);
position: relative;
overflow: auto;
display: flex;
flex-direction: column;
.placeholder {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
}
.item {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #444444;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
}
</style>
Loading…
Cancel
Save