Showing
1 changed file
with
37 additions
and
1 deletions
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | //#region --import--. | 2 | //#region --import--. |
| 3 | import SearchBar from "~/components/SearchBar.vue"; | 3 | import SearchBar from "~/components/SearchBar.vue"; |
| 4 | -import { ref } from "vue"; | 4 | +import { onBeforeUnmount, ref } from "vue"; |
| 5 | import { useTMDB } from "~/composables/tMDB"; | 5 | import { useTMDB } from "~/composables/tMDB"; |
| 6 | import { Movie } from "~/models/movie"; | 6 | import { Movie } from "~/models/movie"; |
| 7 | import { FilmIcon } from "lucide-vue-next"; | 7 | import { FilmIcon } from "lucide-vue-next"; |
| @@ -18,6 +18,10 @@ const isInitialLoading = ref(true); | @@ -18,6 +18,10 @@ const isInitialLoading = ref(true); | ||
| 18 | const isLoadingMore = ref(false); | 18 | const isLoadingMore = ref(false); |
| 19 | const currentPage = ref(1); | 19 | const currentPage = ref(1); |
| 20 | const totalPages = ref(0); | 20 | const totalPages = ref(0); |
| 21 | +/** Elément observé pour le défilement infini. */ | ||
| 22 | +const loadMoreTrigger = ref<HTMLElement | null>(null); | ||
| 23 | +/** Instance de IntersectionObserver */ | ||
| 24 | +const observer = ref<IntersectionObserver | null>(null); | ||
| 21 | //#endregion | 25 | //#endregion |
| 22 | 26 | ||
| 23 | //#region --Computed--. | 27 | //#region --Computed--. |
| @@ -47,12 +51,41 @@ const fetchMovies = async (page: number) => { | @@ -47,12 +51,41 @@ const fetchMovies = async (page: number) => { | ||
| 47 | isLoadingMore.value = false; | 51 | isLoadingMore.value = false; |
| 48 | } | 52 | } |
| 49 | }; | 53 | }; |
| 54 | + | ||
| 55 | +function createIntersectionObserver() { | ||
| 56 | + return new IntersectionObserver( | ||
| 57 | + (entries) => { | ||
| 58 | + const [entry] = entries; | ||
| 59 | + if (entry.isIntersecting && !isLoadingMore.value && currentPage.value < totalPages.value) { | ||
| 60 | + fetchMovies(currentPage.value + 1); | ||
| 61 | + } | ||
| 62 | + }, | ||
| 63 | + { threshold: 1.0 }, | ||
| 64 | + ); | ||
| 65 | +} | ||
| 50 | //#endregion | 66 | //#endregion |
| 51 | 67 | ||
| 52 | //#region --Global event--. | 68 | //#region --Global event--. |
| 53 | onMounted(() => { | 69 | onMounted(() => { |
| 54 | // Chargement des premiers films. | 70 | // Chargement des premiers films. |
| 55 | fetchMovies(1); | 71 | fetchMovies(1); |
| 72 | + // Création et stockage dans la ref de l'instance IntersectionObserver. | ||
| 73 | + observer.value = createIntersectionObserver(); | ||
| 74 | + if (loadMoreTrigger.value) { | ||
| 75 | + // Début d'observation de la div pour le défilement infini. | ||
| 76 | + observer.value.observe(loadMoreTrigger.value); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + if (loadMoreTrigger.value) { | ||
| 80 | + observer.value.observe(loadMoreTrigger.value); | ||
| 81 | + } | ||
| 82 | +}); | ||
| 83 | + | ||
| 84 | +onBeforeUnmount(() => { | ||
| 85 | + // Disconnect the observer when the component is unmounted | ||
| 86 | + if (observer.value) { | ||
| 87 | + observer.value.disconnect(); | ||
| 88 | + } | ||
| 56 | }); | 89 | }); |
| 57 | //#endregion | 90 | //#endregion |
| 58 | </script> | 91 | </script> |
| @@ -94,6 +127,9 @@ onMounted(() => { | @@ -94,6 +127,9 @@ onMounted(() => { | ||
| 94 | </div> | 127 | </div> |
| 95 | </div> | 128 | </div> |
| 96 | </div> | 129 | </div> |
| 130 | + | ||
| 131 | + <!-- Élément observé pour le défilement infini --> | ||
| 132 | + <div ref="loadMoreTrigger" class="h-10 mt-4"/> | ||
| 97 | </section> | 133 | </section> |
| 98 | </template> | 134 | </template> |
| 99 | 135 |
-
Please register or login to post a comment