Bruno Predot

Création et gestion de l'observer pour le défilement infini.

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