<template>
<div class="container">
<div class="list">
<div v-for="(item, index) in data" :key="index" class="list-item">
{{ item }}
</div>
<div
v-if="!allDataLoaded"
ref="observerElement"
class="observer-element"
></div>
</div>
</div>
<div v-show="loading" class="loading">
<h1>加载中...</h1>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
const data = ref<any[]>([]);
const allDataLoaded = ref(false); // 新增变量,用于判断是否所有数据已加载
const observerElement = ref(); // 新增引用,用于观察元素
const loading = ref(false);
onMounted(async () => {
await loadMore();
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && !loading.value && !allDataLoaded.value) {
loadMore();
}
},
{
root: null,
rootMargin: "0px",
threshold: 1.0,
}
)
observer.observe(observerElement.value);
});
const loadMore = async () => {
if (loading.value) return; // 如果已经在加载,则不再触发
loading.value = true;
// 模拟异步加载数据
setTimeout(() => {
const newData = new Array(10).fill(0).map((_, i) => data.value.length + i);
data.value.push(...newData);
loading.value = false;
// 如果数据加载完毕,设置allDataLoaded为true
}, 1000);
};
</script>
<style scoped>
.container {
height: 600px;
overflow: auto; /* 添加滚动 */
width: 300px;
}
.list {
height: 100%;
width: 98%;
}
.list-item {
width: 100%;
height: 50px;
border: 1px solid #e01d1d;
}
.observer-element {
height: 50px; /* 观察元素高度 */
}
.loading {
position: fixed; /* 固定位置 */
top: 0; /* 顶部对齐 */
left: 0; /* 左侧对齐 */
width: 100%; /* 宽度填满视口 */
height: 100%; /* 高度填满视口 */
background-color: rgba(255, 255, 255, 0.8); /* 半透明背景 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
z-index: 1000; /* 确保在最上层 */
}
</style>