feat: 定高item实现虚拟列表变量优化

master
LCJ-MinYa 10 months ago
parent 76a0215625
commit 8ba78f6f6d

@ -1,43 +1,45 @@
<template> <template>
<!-- 容器组件高度一定要是确定的高度不能由内容撑起 --> <base-container>
<div <!-- 容器组件高度一定要是确定的高度不能由内容撑起 -->
class="virtual-list-container"
ref="virtualListContainer"
@scroll="handleScroll($event)"
>
<!-- 绝对定位当父组件overflow:auto时占位组件可以撑起滚动条 -->
<div <div
class="placeholder" class="container"
:style="{ height: `${totalHeight}px` }" ref="containerRef"
></div> @scroll="handleScroll($event)"
<!-- 偏移量设置在每个item的父容器上面 --> >
<div :style="{ transform: getTransform }"> <!-- 绝对定位当父组件overflow:auto时占位组件可以撑起滚动条 -->
<div <div
v-for="item in renderList" class="placeholder"
:key="item.id" :style="{ height: `${listHeight}px` }"
class="item" ></div>
:style="{ height: `${itemHeight}px` }" <!-- 偏移量设置在每个item的父容器上面 -->
> <div :style="{ transform: getTransform }">
{{ item.text }} <div
v-for="item in renderList"
:key="item.id"
class="item"
:style="{ height: `${itemHeight}px` }"
>
{{ item.text }}
</div>
</div> </div>
</div> </div>
</div> </base-container>
</template> </template>
<script setup> <script setup>
import { ref, computed, onMounted } from 'vue'; 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}` })); const dataList = Array.from({ length: 1000 }, (_, i) => ({ id: i, text: `Item ${i}` }));
/** 虚拟列表单条item的高度 */ /** 虚拟列表单条item的高度 */
const itemHeight = 100; const itemHeight = 100;
/** 虚拟列表的总高度 */ /** 虚拟列表的总高度 */
const totalHeight = dataList.length * itemHeight; const listHeight = computed(() => dataList.length * itemHeight);
/** 虚拟列表容器 */
const containerRef = ref(null);
/** 虚拟列表容器高度 */
const containerHeight = ref(0);
const renderCount = computed(() => { const renderCount = computed(() => {
console.log('renderCount数量为', Math.ceil(containerHeight.value / itemHeight)); console.log('renderCount数量为', Math.ceil(containerHeight.value / itemHeight));
return Math.ceil(containerHeight.value / itemHeight); return Math.ceil(containerHeight.value / itemHeight);
@ -47,13 +49,13 @@ const renderCount = computed(() => {
const start = ref(0); const start = ref(0);
/** 虚拟列表当前可见区域的结束索引 */ /** 虚拟列表当前可见区域的结束索引 */
const end = computed(() => { const end = computed(() => {
console.log('end索引为', start.value + renderCount.value);
return start.value + renderCount.value; return start.value + renderCount.value;
}); });
/** 虚拟列表当前可见区域的偏移量 */ /** 虚拟列表当前可见区域的偏移量 */
const offset = ref(0); const offset = ref(0);
const renderList = computed(() => { const renderList = computed(() => {
console.log('renderList数据为', dataList.slice(start.value, end.value + 1)); console.log('renderList数据为', dataList.slice(start.value, end.value + 1));
/** 这里ender.value + 1是为了确保渲染一定超过一屏的高度 */
return dataList.slice(start.value, end.value + 1); return dataList.slice(start.value, end.value + 1);
}); });
@ -76,7 +78,7 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.virtual-list-container { .virtual-list-container {
width: 100%; width: 100%;
height: calc(100vh - 81px); height: 100%;
position: relative; position: relative;
overflow: auto; overflow: auto;
display: flex; display: flex;

Loading…
Cancel
Save