Skip to content

useLoadMore

useLoadMore 用于实现 加载更多 / 无限滚动 场景:首屏加载一页数据,随后通过按钮或滚动条持续追加后续数据。

基础用法

typescript
import { useLoadMore } from '@yh-ui/request'

interface UserList {
  list: User[]
  total: number
}

const {
  data, // ShallowRef<UserList | undefined>
  loading, // 首次加载状态
  loadingMore, // 加载更多状态
  noMore, // 是否没有更多
  loadMore, // 加载更多
  reload // 重新加载(重置分页)
} = useLoadMore<UserList>(
  (page, pageSize) =>
    request.get('/api/users', {
      params: { page, pageSize }
    }),
  {
    initialPage: 1,
    pageSize: 10
  }
)

模板示例:

vue
<template>
  <yh-list :data="data?.list || []" />

  <div style="margin-top: 16px; text-align: center;">
    <yh-button type="primary" :loading="loadingMore" :disabled="noMore" @click="loadMore">
      {{ noMore ? '没有更多了' : '加载更多' }}
    </yh-button>
  </div>
</template>

返回值

typescript
const result = useLoadMore<TData>(service, options)
字段类型说明
currentRef<number>当前页码
pageSizeRef<number>每页条数
totalRef<number>总数
totalPagesRef<number>总页数
dataShallowRef<TData | undefined>数据(通常为数组或带 list 的对象)
loadingRef<boolean>首屏加载中
refreshingRef<boolean>刷新中
loadingMoreRef<boolean>正在加载更多
errorShallowRef<unknown>错误
paramsRef<unknown[]>额外参数
noMoreRef<boolean>是否没有更多
canLoadMoreRef<boolean>是否可以加载更多
loadMore()加载下一页并追加数据
reload()重置并重新加载
refresh()刷新当前数据
pagination一组分页工具方法(与 usePagination 接口兼容)

选项

useLoadMore(service, options) 的第一个参数为请求函数 service(page, pageSize, ...args),第二个参数为配置项:

typescript
interface UseLoadMoreOptions<TData, TParams extends unknown[]> {
  initialPage?: number // 初始页码,默认 1
  pageSize?: number // 每页条数,默认 10
  isLoadMore?: boolean // 是否允许加载更多,默认 true
  threshold?: number // 无限滚动触底阈值(预留)
  loadMoreService?: (page: number, pageSize: number) => Promise<RequestResponse<TData>> // 加载更多时使用的请求(可与 service 不同)
  onSuccess?: (data: TData, params: TParams) => void
  onError?: (error: unknown, params: TParams) => void
  onFinally?: (params: TParams) => void
  manual?: boolean // 是否手动触发首次加载
  defaultParams?: TParams // 除 page、pageSize 外的额外参数
}

追加列表数据

data 为数组时,useLoadMore 会自动在加载更多时做 数组拼接

typescript
// data: Ref<User[]>
const { data, loadMore } = useLoadMore<User[]>((page, pageSize) =>
  request.get('/api/users', { params: { page, pageSize } })
)

// 第一次加载:data = 第 1 页
// 第二次 loadMore:data = 第 1 页 + 第 2 页

当返回结构为 { list, total } 时,同样会执行追加:

typescript
interface PageResult<T> {
  list: T[]
  total: number
}

const { data, loadMore } = useLoadMore<PageResult<User>>((page, pageSize) =>
  request.get('/api/users', { params: { page, pageSize } })
)

手动刷新与重新加载

typescript
const { reload, refresh } = useLoadMore(
  (page, size) => request.get('/api/logs', { params: { page, pageSize: size } }),
  {
    manual: true
  }
)

// 首次加载
reload()

// 基于当前分页刷新(通常用于筛选条件变化后)
refresh()

与滚动事件结合

你可以在滚动容器中监听滚动事件,在接近底部时触发 loadMore

vue
<template>
  <div ref="scrollRef" style="height: 400px; overflow: auto;" @scroll="handleScroll">
    <yh-list :data="data || []" />
  </div>
</template>
typescript
const scrollRef = ref<HTMLElement>()

const handleScroll = () => {
  const el = scrollRef.value
  if (!el || !canLoadMore.value) return

  const distanceToBottom = el.scrollHeight - el.scrollTop - el.clientHeight
  if (distanceToBottom < 100) {
    loadMore()
  }
}

与 usePagination 的关系

  • usePagination:适合「有明确分页控件」的场景(页码切换)
  • useLoadMore:适合「瀑布流 / 无限滚动」场景(不断往下追加)

两者的 pagination 返回值基本兼容,可以在需要时互相切换实现方式。

Released under the MIT License.