Selaa lähdekoodia

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

liaochunxin 7 kuukautta sitten
vanhempi
commit
3874a031a9
3 muutettua tiedostoa jossa 156 lisäystä ja 0 poistoa
  1. 74 0
      src/hooks/useScroll.ts
  2. 10 0
      src/pages/about/about.vue
  3. 72 0
      src/pages/demo/scroll.vue

+ 74 - 0
src/hooks/useScroll.ts

@@ -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,
+  }
+}

+ 10 - 0
src/pages/about/about.vue

@@ -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 - 0
src/pages/demo/scroll.vue

@@ -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>