Skip to content
On this page

useInfiniteScroll

useInfiniteScroll 封装了常见的无限滚动逻辑。

const { data, loading, loadingMore, loadMore } = useInfiniteScroll(service)
const { data, loading, loadingMore, loadMore } = useInfiniteScroll(service)

useInfiniteScroll 的第一个参数 service 是一个异步函数,对这个函数的入参和出参有如下约定:

  1. service 返回的数据必须包含 list 数组,类型为 { list: any[], ...rest }
  2. service 的入参为整合后的最新 data

假如第一次请求返回数据为 { list: [1, 2, 3], nextId: 4 }, 第二次返回的数据为 { list: [4, 5, 6], nextId: 7 }, 则我们会自动合并 list,整合后的的 data{ list: [1, 2, 3, 4, 5, 6], nextId: 7 }

基础用法

第一个例子我们演示最基本的无限滚动写法。

分页

在数据固定场景下,我们有时候会用 pagepageSize 来请求新的分页数据。

滚动自动加载

在无限滚动场景中,我们最常见的是滚动到底部时自动加载。通过配置以下几个属性,即可实现滚动自动加载。

  • options.target 指定父级元素(父级元素需设置固定高度,且支持内部滚动)
  • options.isNoMore 判断是不是没有更多数据了

数据重置

通过 reload 即可实现数据重置,重置数据到第一页。

以上代码可以通过 reloadDeps 语法糖实现,当 reloadDeps 变化时,会自动触发 reload

数据突变

通过 mutate,我们可以直接修改当前 data。下面示例演示了删除某条数据。

API

export type Data = { list: any[];[key: string]: any; };
export type Service<TData extends Data> = (currentData?: TData) => Promise<TData>;

const {
  data: Ref<TData>;
  loading: ComputedRef<boolean>;
  loadingMore: Ref<boolean>;
  noMore: ComputedRef<boolean>;
  loadMore: () => void;
  loadMoreAsync: () => Promise<TData>;
  reload: () => void;
  reloadAsync: () => Promise<TData>;
  cancel: () => void;
  mutate: (data?: TData) => void;
} = useInfiniteScroll<TData extends Data>(
  service: (currentData?: TData) => Promise<TData>,
  {
    target?: BasicTarget;
    isNoMore?: (data?: TData) => boolean;
    threshold?: number;
    manual?: boolean;
    reloadDeps?: DependencyList;
    onBefore?: () => void;
    onSuccess?: (data: TData) => void;
    onError?: (e: Error) => void;
    onFinally?: (data?: TData, e?: Error) => void;
  }
);
export type Data = { list: any[];[key: string]: any; };
export type Service<TData extends Data> = (currentData?: TData) => Promise<TData>;

const {
  data: Ref<TData>;
  loading: ComputedRef<boolean>;
  loadingMore: Ref<boolean>;
  noMore: ComputedRef<boolean>;
  loadMore: () => void;
  loadMoreAsync: () => Promise<TData>;
  reload: () => void;
  reloadAsync: () => Promise<TData>;
  cancel: () => void;
  mutate: (data?: TData) => void;
} = useInfiniteScroll<TData extends Data>(
  service: (currentData?: TData) => Promise<TData>,
  {
    target?: BasicTarget;
    isNoMore?: (data?: TData) => boolean;
    threshold?: number;
    manual?: boolean;
    reloadDeps?: DependencyList;
    onBefore?: () => void;
    onSuccess?: (data: TData) => void;
    onError?: (e: Error) => void;
    onFinally?: (data?: TData, e?: Error) => void;
  }
);

Result

参数说明类型
dataservice 返回的数据,其中的 list 属性为聚合后数据Readonly<Ref<TData>> | undefined
loading是否正在进行首次请求ComputedRef<boolean>
loadingMore是否正在进行更多数据请求Readonly<Ref<boolean>>
noMore是否没有更多数据了,配置 options.isNoMore 后生效ComputedRef<boolean>
loadMore加载更多数据,会自动捕获异常,通过 options.onError 处理() => void
loadMoreAsync加载更多数据,与 loadMore 行为一致,但返回的是 Promise,需要自行处理异常() => Promise<TData>
reload加载第一页数据,会自动捕获异常,通过 options.onError 处理() => void
reloadAsync加载第一页数据,与 reload 行为一致,但返回的是 Promise,需要自行处理异常() => Promise<TData>
mutate直接修改 data(data?: TData) => void
cancel忽略当前 Promise 的响应() => void

Options

参数说明类型默认值
target父级容器,如果存在,则在滚动到底部时,自动触发 loadMore。需要配合 isNoMore 使用,以便知道什么时候到最后一页了。() => Element | Element | MutableRefObject<Element>-
isNoMore是否有最后一页的判断逻辑,入参为当前聚合后的 data(data?: TData) => boolean-
threshold下拉自动加载,距离底部距离阈值number100
reloadDeps变化后,会自动触发 reloadWatchSource | any[] |any-
manual
  • 默认 false。 即在初始化时自动执行 service。
  • 如果设置为 true,则需要手动调用 reloadreloadAsync 触发执行。
booleanfalse
onBeforeservice 执行前触发() => void-
onSuccessservice resolve 时触发(data: TData) => void-
onErrorservice reject 时触发(e: Error) => void-
onFinallyservice 执行完成时触发(data?: TData, e?: Error) => void-

Source

源码文档示例