<template>
    <base-container>
        <!-- 容器组件高度一定要是确定的高度，不能由内容撑起 -->
        <div
            class="container"
            ref="containerRef"
            @scroll="handleScroll($event)"
        >
            <!-- 绝对定位，当父组件overflow:auto时，占位组件可以撑起滚动条 -->
            <div
                class="placeholder"
                :style="{ height: `${listHeight}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>
    </base-container>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';

/** 原始数据列表 */
const dataList = Array.from({ length: 1000 }, (_, i) => ({ id: i, text: `Item ${i}` }));
/** 虚拟列表单条item的高度 */
const itemHeight = 100;
/** 虚拟列表的总高度 */
const listHeight = computed(() => dataList.length * itemHeight);

/** 虚拟列表容器 */
const containerRef = ref(null);
/** 虚拟列表容器高度 */
const containerHeight = ref(0);
const renderCount = computed(() => {
    console.log('renderCount数量为：', Math.ceil(containerHeight.value / itemHeight));
    return Math.ceil(containerHeight.value / itemHeight);
});

/** 虚拟列表当前可见区域的起始索引 */
const start = ref(0);
/** 虚拟列表当前可见区域的结束索引 */
const end = computed(() => {
    return start.value + renderCount.value;
});
/** 虚拟列表当前可见区域的偏移量 */
const offset = ref(0);
const renderList = computed(() => {
    console.log('renderList数据为：', dataList.slice(start.value, end.value + 1));
    /** 这里ender.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 = containerRef.value.clientHeight;
    console.log('containerHeight容器高度为：', containerHeight.value);
});
</script>

<style lang="scss" scoped>
.container {
    width: 100%;
    height: 100%;
    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>
