feat: 增加下拉刷新和下拉加载更多 hooks
This commit is contained in:
74
src/hooks/useScroll.ts
Normal file
74
src/hooks/useScroll.ts
Normal 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,
|
||||
}
|
||||
}
|
||||
@@ -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
72
src/pages/demo/scroll.vue
Normal 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>
|
||||
Reference in New Issue
Block a user