uniapp-app/pages_app/myFlower/scrollLoadDemo.vue
2026-03-06 10:44:49 +08:00

154 lines
2.9 KiB
Vue

<template>
<view class="page">
<view class="header">
<text class="title">scroll-view 上拉加载 Demo</text>
<text class="sub">下拉刷新 + 触底加载更多</text>
</view>
<scroll-view
class="list-scroll"
scroll-y
lower-threshold="80"
refresher-enabled
:refresher-triggered="refreshing"
@refresherrefresh="onRefresh"
@scrolltolower="onLoadMore"
>
<view v-for="item in list" :key="item.id" class="list-item">
<text class="item-title">{{ item.title }}</text>
<text class="item-time">{{ item.time }}</text>
</view>
<view v-if="loading" class="tip">加载中...</view>
<view v-else-if="noMore && list.length > 0" class="tip">没有更多数据了</view>
<view v-else-if="list.length === 0" class="tip">暂无数据</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const page = ref(1);
const pageSize = ref(10);
const list = ref([]);
const loading = ref(false);
const refreshing = ref(false);
const noMore = ref(false);
const totalMockCount = 37;
const fullData = Array.from({ length: totalMockCount }, (_, i) => {
const index = i + 1;
return {
id: index,
title: `${index} 条数据`,
time: `2026-03-${String((index % 28) + 1).padStart(2, '0')}`
};
});
const getPageData = (pageNum, size) => {
return new Promise((resolve) => {
setTimeout(() => {
const start = (pageNum - 1) * size;
const end = start + size;
resolve(fullData.slice(start, end));
}, 350);
});
};
const fetchList = async (isRefresh = false) => {
if (loading.value) return;
loading.value = true;
try {
if (isRefresh) {
page.value = 1;
noMore.value = false;
}
const rows = await getPageData(page.value, pageSize.value);
if (isRefresh) {
list.value = rows;
} else {
list.value = [...list.value, ...rows];
}
noMore.value = rows.length < pageSize.value;
} finally {
loading.value = false;
refreshing.value = false;
}
};
const onRefresh = async () => {
if (refreshing.value) return;
refreshing.value = true;
await fetchList(true);
};
const onLoadMore = async () => {
if (loading.value || refreshing.value || noMore.value) return;
page.value += 1;
await fetchList(false);
};
onMounted(() => {
fetchList(true);
});
</script>
<style scoped>
.page {
height: 100vh;
background: #f7f8fa;
}
.header {
padding: 30rpx;
background: #ffffff;
border-bottom: 1rpx solid #ededed;
}
.title {
display: block;
font-size: 34rpx;
color: #222;
font-weight: 600;
}
.sub {
display: block;
margin-top: 8rpx;
font-size: 24rpx;
color: #888;
}
.list-scroll {
height: calc(100vh - 130rpx);
}
.list-item {
margin: 20rpx 24rpx 0;
padding: 24rpx;
background: #ffffff;
border-radius: 12rpx;
}
.item-title {
display: block;
font-size: 30rpx;
color: #222;
}
.item-time {
display: block;
margin-top: 10rpx;
font-size: 24rpx;
color: #999;
}
.tip {
padding: 28rpx 0 40rpx;
text-align: center;
color: #9aa0a6;
font-size: 24rpx;
}
</style>