5 min de lecture
124 vues

Infinite Scroll avec Inertia.js : Guide complet pour Laravel + Vue 3

Infinite Scroll avec Inertia.js : Guide complet pour Laravel + Vue 3

L’infinite scroll (défilement infini) transforme l’expérience utilisateur en chargeant du contenu de façon fluide, sans pagination intrusive. Grâce à Inertia.js v2+, cette fonctionnalité est désormais native, performante et facile à implémenter dans une stack Laravel + Vue 3.

Contrairement aux solutions manuelles (gestion d’API, état, scroll, erreurs), Inertia.js fournit une intégration full-stack cohérente : le backend prépare les données, le frontend les consomme intelligemment — avec fusion automatique, synchronisation d’URL, et gestion fine du chargement.


Sommaire

  1. Pourquoi utiliser l’infinite scroll ?
  2. Prérequis techniques
  3. Configuration côté serveur (Laravel)
  4. Mise en place côté client (Vue 3)
  5. Fonctionnalités avancées
  6. Bonnes pratiques
  7. Conclusion

Pourquoi utiliser l’infinite scroll ?

L’infinite scroll améliore :

  • L’engagement utilisateur : pas de clics répétitifs sur « page suivante ».
  • La fluidité : le contenu arrive naturellement au scroll.
  • La modernité : attendu sur les réseaux sociaux, blogs, marketplaces, chats.

⚠️ À utiliser avec discernement : il n’est pas adapté à tous les cas (ex. résultats de recherche paginés où la navigation précise est utile).


Prérequis techniques

Assurez-vous d’utiliser les versions minimales suivantes :

  • Frontend : @inertiajs/vue3 ≥ v2.2.0
  • Backend : inertiajs/inertia-laravel ≥ v2.0.10

Mettez à jour si nécessaire :

npm install @inertiajs/vue3@latest
composer require inertiajs/inertia-laravel:^2.0

Configuration côté serveur (Laravel)

Utilisez Inertia::scroll() pour préparer vos données paginées. Cette méthode :

  • Normalise les métadonnées de pagination (next, prev, current_page, etc.)
  • Active la fusion automatique côté frontend (ajout, pas remplacement)
use Inertia\Inertia;
 
Route::get('/blog', function () {
$posts = Post::published()
->with('category')
->latest()
->paginate(6);
 
return Inertia::render('Blog/Index', [
'posts' => Inertia::scroll($posts),
]);
});

✅ Compatible avec :

  • paginate()
  • simplePaginate()
  • cursorPaginate()
  • Eloquent API Resources

💡 Astuce : Si vous filtrez les données (ex. par catégorie), réinitialisez le scroll avec reset: ['posts'] dans vos requêtes Inertia :

router.visit('/blog', { data: { category: 'dev' }, reset: ['posts'] });

Mise en place côté client (Vue 3)

Le composant <InfiniteScroll> gère tout : détection du scroll, chargement, fusion.

🔹 Structure de base

<template>
<InfiniteScroll data="posts">
<article v-for="post in posts.data" :key="post.id">
{{ post.title }}
</article>
</InfiniteScroll>
</template>
 
<script setup>
import { InfiniteScroll } from '@inertiajs/vue3'
</script>

Le prop data="posts" correspond à la clé utilisée dans Inertia::render([... 'posts' => ...]).


Fonctionnalités avancées

1. Chargement anticipé (buffer)

Charge le contenu avant d’atteindre la fin :

<InfiniteScroll data="posts" :buffer="800" />

Plus la valeur est élevée, plus le chargement est précoce — mais risque de charger du contenu inutile.


2. Synchronisation d’URL

Par défaut, l’URL est mise à jour avec ?page=2, ?page=3, etc., selon la page la plus visible.

Désactivez-le pour du contenu secondaire :

<InfiniteScroll data="comments" preserve-url />

3. Mode manuel après N pages

Idéal pour limiter les appels automatiques :

<InfiniteScroll data="posts" :manual-after="3">
<template #next="{ loading, fetch, hasMore, manualMode }">
<button v-if="manualMode && hasMore" @click="fetch" :disabled="loading">
<Loader2 v-if="loading" class="animate-spin" />
{{ loading ? 'Chargement...' : 'Charger plus' }}
</button>
</template>
</InfiniteScroll>

Les slots #previous et #next reçoivent :

  • loading, loadingNext, loadingPrevious
  • fetch() → déclenche le chargement
  • hasMore, hasNext, hasPrevious
  • manualMode / autoMode

4. Slot de chargement par défaut

<template #loading>
<div class="text-center py-4 text-muted">Chargement des articles…</div>
</template>

Affiché pendant le chargement automatique si aucun slot before/after n’est fourni.


5. Chargement dans les deux sens

Par défaut, le composant charge vers le haut et vers le bas.

Restreignez la direction :

<!-- Seulement vers le bas -->
<InfiniteScroll data="posts" only-next />
 
<!-- Seulement vers le haut -->
<InfiniteScroll data="messages" only-previous />

6. Mode inversé (chat, timeline)

Pour les interfaces où les nouveaux éléments sont en bas :

<InfiniteScroll data="messages" reverse :auto-scroll="false">
<!-- Messages du plus ancien au plus récent -->
</InfiniteScroll>

⚠️ Triez vos données correctement côté serveur. Le composant gère le scroll, pas l’ordre.


7. Conteneurs de scroll personnalisés

Fonctionne dans n’importe quel conteneur scrollable :

<div style="height: 500px; overflow-y: auto;">
<InfiniteScroll data="posts">...</InfiniteScroll>
</div>

8. Plusieurs scrolls sur une même page

Évitez les conflits d’URL avec pageName :

// Backend
'users' => Inertia::scroll(User::paginate(pageName: 'users')),
'orders' => Inertia::scroll(Order::paginate(pageName: 'orders')),

→ URL : ?users=2&orders=3


9. Accès programmatique

<script setup>
import { ref } from 'vue'
const scrollRef = ref()
 
const loadMore = () => scrollRef.value?.fetchNext()
</script>
 
<template>
<button @click="loadMore">Charger plus</button>
<InfiniteScroll ref="scrollRef" data="posts" manual />
</template>

Méthodes exposées : fetchNext(), fetchPrevious(), hasNext(), hasPrevious().


10. Ciblage d’éléments (tables, listes complexes)

Pour les <table>, <ul>, etc. :

<InfiniteScroll data="users" items-element="#table-body">
<table>
<tbody id="table-body">
<tr v-for="user in users.data" :key="user.id">...</tr>
</tbody>
</table>
</InfiniteScroll>

Ou avec des ref :

<InfiniteScroll
:items-element="() => tableBody"
:start-element="() => tableHeader"
:end-element="() => tableFooter"
>

Bonnes pratiques

Recommandation Raison
6–10 éléments/page Équilibre UX/performance
Optimisez les requêtes (with(), select()) Réduisez la taille des payloads
Prévoyez un fallback (bouton "Charger plus") Accessibilité (JS désactivé, préférences utilisateur)
Évitez les composants lourds dans les listes Performance du scroll
Réinitialisez avec reset lors de changement de filtre Évite le mélange de résultats
Testez sur mobile Le scroll peut être plus sensible

Conclusion

Avec Inertia::scroll() et <InfiniteScroll>, vous bénéficiez d’une solution full-stack cohérente, performante et riche en fonctionnalités, sans avoir à gérer manuellement les appels API, la fusion d’état ou la gestion du scroll.

C’est l’outil idéal pour :

  • Blogs et flux d’articles
  • Réseaux sociaux
  • Marketplaces
  • Interfaces de chat
  • Timelines d’activité

Grâce à Inertia.js, l’infinite scroll devient simple, fiable et maintenable — même dans des applications complexes.


Ressources officielles


Prêt à moderniser votre interface ? Implémentez l’infinite scroll dès aujourd’hui et offrez une expérience utilisateur fluide et engageante.