feat: 增加下拉刷新和下拉加载更多 hooks

This commit is contained in:
liaochunxin
2025-09-28 17:12:27 +08:00
parent ceebd31885
commit 3874a031a9
3 changed files with 156 additions and 0 deletions

74
src/hooks/useScroll.ts Normal file
View File

@@ -0,0 +1,74 @@
import type { Ref } from 'vue'
import { onMounted, ref } from 'vue'
interface UseScrollOptions<T> {
fetchData: (page: number, pageSize: number) => Promise<T[]>
pageSize?: number
}
interface UseScrollReturn<T> {
list: Ref<T[]>
loading: Ref<boolean>
finished: Ref<boolean>
error: Ref<any>
refresh: () => Promise<void>
loadMore: () => Promise<void>
}
export function useScroll<T>({
fetchData,
pageSize = 10,
}: UseScrollOptions<T>): UseScrollReturn<T> {
const list = ref<T[]>([]) as Ref<T[]>
const loading = ref(false)
const finished = ref(false)
const error = ref<any>(null)
const page = ref(1)
const loadData = async () => {
if (loading.value || finished.value)
return
loading.value = true
error.value = null
try {
const data = await fetchData(page.value, pageSize)
if (data.length < pageSize) {
finished.value = true
}
list.value.push(...data)
page.value++
}
catch (err) {
error.value = err
}
finally {
loading.value = false
}
}
const refresh = async () => {
page.value = 1
finished.value = false
list.value = []
await loadData()
}
const loadMore = async () => {
await loadData()
}
onMounted(() => {
refresh()
})
return {
list,
loading,
finished,
error,
refresh,
loadMore,
}
}

View File

@@ -46,6 +46,11 @@ function gotoTabbar() {
url: '/pages/index/index',
})
}
function gotoScroll() {
uni.navigateTo({
url: '/pages/demo/scroll',
})
}
// #region setTabbarBadge
function setTabbarBadge() {
tabbarStore.setTabbarItemBadge(1, 100)
@@ -116,6 +121,11 @@ onShow(() => {
<RequestComp />
<VBindCss />
<view class="mb-6 h-1px bg-#eee" />
<view class="text-center">
<button type="primary" size="mini" class="w-160px" @click="gotoScroll">
下拉刷新和下拉加载更多 简单hooks非z-paging组件
</button>
</view>
<view class="text-center">
<button type="primary" size="mini" class="w-160px" @click="gotoAlova">
前往 alova 示例页面

72
src/pages/demo/scroll.vue Normal file
View File

@@ -0,0 +1,72 @@
<script setup lang="ts">
// uniapp 页面生命周期
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
import { useScroll } from '@/hooks/useScroll'
definePage({
style: {
navigationBarTitleText: '下拉刷新和下拉加载更多',
enablePullDownRefresh: true,
onReachBottomDistance: 100,
},
})
// 模拟异步获取数据的函数
function mockFetchData(page: number, pageSize: number): Promise<{ id: number, name: string }[]> {
return new Promise((resolve) => {
setTimeout(() => {
if (page > 5) {
// 模拟没有更多数据
resolve([])
return
}
const data = Array.from({ length: pageSize }, (_, i) => ({
id: (page - 1) * pageSize + i + 1,
name: `item ${(page - 1) * pageSize + i + 1}`,
}))
resolve(data)
}, 1000)
})
}
const { list, loading, finished, error, refresh, loadMore } = useScroll({
fetchData: mockFetchData,
pageSize: 10,
})
onPullDownRefresh(async () => {
console.log('onPullDownRefresh')
console.log('onPullDownRefresh')
console.log('onPullDownRefresh')
await refresh()
uni.stopPullDownRefresh()
})
onReachBottom(() => {
loadMore()
})
</script>
<template>
<view class="h-screen p-4">
<view v-if="error" class="text-center text-red-500">
加载失败请重试
</view>
<view v-else>
<view
v-for="item in list"
:key="item.id"
class="my-2 h-20 flex items-center justify-center rounded bg-gray-100"
>
{{ item.name }}
</view>
<view v-if="loading" class="py-4 text-center text-gray-500">
加载中...
</view>
<view v-if="finished" class="py-4 text-center text-gray-500">
没有更多了
</view>
</view>
</view>
</template>