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