47 lines
1.2 KiB
TypeScript
47 lines
1.2 KiB
TypeScript
// composables/useInfiniteScrollObserver.ts
|
|
import { onBeforeUnmount, onMounted, ref } from "vue";
|
|
|
|
export default function useInfiniteScrollObserver(callback) {
|
|
const observer = ref<IntersectionObserver | null>(null);
|
|
const isFetching = ref(false);
|
|
const infiniteScroll = ref<HTMLElement | null>(null);
|
|
console.info("useInfiniteScrollObserver");
|
|
|
|
const initObserver = () => {
|
|
console.info("useInfiniteScrollObserver");
|
|
|
|
observer.value = new IntersectionObserver(
|
|
(entries) => {
|
|
console.info("useInfiniteScrollObserver");
|
|
|
|
if (entries[0].isIntersecting && !isFetching.value) {
|
|
isFetching.value = true;
|
|
callback().finally(() => {
|
|
isFetching.value = false;
|
|
});
|
|
}
|
|
},
|
|
{
|
|
rootMargin: "200px", // Load when 200px away from viewport
|
|
threshold: 0.1,
|
|
}
|
|
);
|
|
|
|
if (infiniteScroll.value) {
|
|
observer.value.observe(infiniteScroll.value);
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
initObserver();
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
if (observer.value && infiniteScroll.value) {
|
|
observer.value.unobserve(infiniteScroll.value);
|
|
}
|
|
});
|
|
|
|
return { isFetching, infiniteScroll };
|
|
}
|