UNPKG

vue-hooks-plus

Version:
115 lines (114 loc) 2.87 kB
import { ref, computed, watch, shallowReadonly, readonly } from "vue"; import useBoolean from "../useBoolean"; import useEventListener from "../useEventListener"; import useRequest from "../useRequest"; import { getTargetElement } from "../utils/domTarget"; import { getScrollTop, getScrollHeight, getClientHeight } from "../utils/rect"; const useInfiniteScroll = (service, options = {}) => { const { target, isNoMore, threshold = 100, reloadDeps = [], manual, onBefore, onSuccess, onError, onFinally } = options; const finalData = ref(); const [loadingMore, { set: setLoadingMore }] = useBoolean(); const setFinalData = (mutateData) => { finalData.value = mutateData; }; const noMore = computed(() => { if (!isNoMore) return false; return isNoMore(finalData.value); }); const { loading, run, runAsync, cancel } = useRequest( async (lastData) => { const currentData = await service(lastData); if (!lastData) { finalData.value = currentData; } else { finalData.value = { ...currentData, list: [...lastData.list, ...currentData.list] }; } return currentData; }, { manual, onFinally: (_, d, e) => { setLoadingMore(false); onFinally == null ? void 0 : onFinally(d, e); }, onBefore: () => onBefore == null ? void 0 : onBefore(), onSuccess: (d) => { setTimeout(() => { scrollMethod(); }); onSuccess == null ? void 0 : onSuccess(d); }, onError: (e) => onError == null ? void 0 : onError(e) } ); const loadMore = () => { if (noMore.value) return; setLoadingMore(true); run(finalData.value); }; const loadMoreAsync = () => { if (noMore.value) return; setLoadingMore(true); return runAsync(finalData.value); }; const reload = () => run(); const reloadAsync = () => runAsync(); const scrollMethod = () => { const el = getTargetElement(target); if (!el) { return; } const scrollTop = getScrollTop(el); const scrollHeight = getScrollHeight(el); const clientHeight = getClientHeight(el); if (scrollHeight - scrollTop <= clientHeight + threshold) { loadMore(); } }; useEventListener( "scroll", () => { if (loading.value || loadingMore.value) { return; } scrollMethod(); }, { target } ); watch(reloadDeps, () => { run(); }); const _loading = computed(() => !loadingMore.value && loading.value); return { data: shallowReadonly(finalData), loading: readonly(_loading), loadingMore, noMore, loadMore, loadMoreAsync, reload, reloadAsync, mutate: setFinalData, scrollMethod, cancel }; }; export { useInfiniteScroll as default };