@thy-rathana/nuxt-infinite-scroll
Version:
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
106 lines (104 loc) • 2.45 kB
JavaScript
import {
useTimer
} from "./chunk-GP2GZZPI.js";
// composables/useNuxtInfiniteScroll.ts
import { ref, unref, watch } from "vue";
import { useInfiniteScroll } from "@vueuse/core";
async function useNuxtInfiniteScroll({
fetchFn,
filters,
pageSize = 12,
distance = 100
}) {
const { addTimer } = useTimer();
const page = ref(1);
const items = ref([]);
const isLoading = ref(false);
const isNoData = ref(false);
const data = ref({});
const targetElement = ref(null);
const isEnd = ref(false);
const fetchMore = async (callbackFc) => {
if (isLoading.value || isEnd.value) return;
isLoading.value = true;
const query = {
...unref(filters),
page: page.value,
page_size: pageSize
};
const response = await fetchFn(
query
);
let result;
if (response && Array.isArray(response.list)) {
result = response.list;
data.value = response;
} else {
result = [];
}
if (result?.length) {
items.value.push(...result);
page.value++;
isNoData.value = false;
} else {
isNoData.value = page.value === 1;
isEnd.value = true;
}
if (result?.length < pageSize) {
isEnd.value = true;
}
isLoading.value = false;
callbackFc?.();
};
const reset = () => {
page.value = 1;
isEnd.value = false;
items.value = [];
data.value = {};
isNoData.value = false;
ifDistanceStillFarFetchMore();
};
const ifDistanceStillFarFetchMore = async () => {
await fetchMore(() => {
addTimer(async () => {
if (canLoadMore(targetElement.value)) {
await ifDistanceStillFarFetchMore();
}
}, 0);
});
};
watch(() => unref(filters), reset, { deep: true });
const canLoadMore = (el) => {
if (isLoading.value || isEnd.value) return false;
if (!el) return false;
const { bottom } = el.getBoundingClientRect();
const { innerHeight } = window;
return bottom <= innerHeight + distance;
};
const loadInfiniteScroll = () => {
useInfiniteScroll(targetElement, () => fetchMore(), {
distance,
canLoadMore
});
};
const setTarget = (el) => {
if (el) {
targetElement.value = el;
loadInfiniteScroll();
}
};
await ifDistanceStillFarFetchMore();
return {
data,
items,
isLoading,
isEnd,
isNoData,
reset,
fetchMore,
setTarget
};
}
export {
useNuxtInfiniteScroll
};