useInfiniteScroll
useInfiniteScroll 封装了常见的无限滚动逻辑。
const { data, loading, loadingMore, loadMore } = useInfiniteScroll(service)
const { data, loading, loadingMore, loadMore } = useInfiniteScroll(service)
useInfiniteScroll 的第一个参数 service
是一个异步函数,对这个函数的入参和出参有如下约定:
service
返回的数据必须包含list
数组,类型为{ list: any[], ...rest }
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 }
。
基础用法
第一个例子我们演示最基本的无限滚动写法。
分页
在数据固定场景下,我们有时候会用 page
和 pageSize
来请求新的分页数据。
滚动自动加载
在无限滚动场景中,我们最常见的是滚动到底部时自动加载。通过配置以下几个属性,即可实现滚动自动加载。
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
参数 | 说明 | 类型 |
---|---|---|
data | service 返回的数据,其中的 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 | 下拉自动加载,距离底部距离阈值 | number | 100 |
reloadDeps | 变化后,会自动触发 reload | WatchSource | any[] |any | - |
manual |
| boolean | false |
onBefore | service 执行前触发 | () => void | - |
onSuccess | service resolve 时触发 | (data: TData) => void | - |
onError | service reject 时触发 | (e: Error) => void | - |
onFinally | service 执行完成时触发 | (data?: TData, e?: Error) => void | - |