Paginer les données Firestore lors de l'utilisation de Vuex et ajouter de nouvelles données à l'état

2020-06-29 javascript vue.js vuex vuexfire

J'ai implémenté ce qui suit pour afficher une requête paginée (cela a été suggéré par Tony O'Hagan dans ce post: Comment obtenir le dernier document d'une requête VueFire ):

bindUsers: firestoreAction(({ bindFirestoreRef }) => {
  return bindFirestoreRef('users', 
      Firebase.firestore().collection('users').limit(8), { serialize })
}),
bindMoreUsers: firestoreAction(context => {
  return context.bindFirestoreRef('users', Firebase.firestore().collection('users').startAfter(context.state.users[context.state.users.length - 1]._doc).limit(8), { serialize })
})

Lorsque l'utilisateur défile jusqu'à la fin de la page, j'appelle bindMoreUsers qui met à jour les state.users vers le prochain ensemble de 8 documents. Je dois être en mesure d'ajouter à l'état.users plutôt que d'écraser l'ensemble original de 8 documents. Comment puis-je faire ceci?

Answers

Confession: je n'ai pas encore implémenté la pagination sur mon application actuelle, mais voici comment je l'aborderais.

Dans ma réponse précédente, j'ai expliqué comment conserver les références aux objets doc Firestore à l'intérieur de chaque élément du tableau d'état lié par VuexFire ou VueFire. Dans la solution n ° 1 ci-dessous, nous utilisons ces objets doc pour implémenter la pagination basée sur le curseur recommandée par Firestore d'un ensemble de résultats de requête en utilisant la condition de requête startAfter(doc) au lieu de la clause de offset plus lente et plus coûteuse.

Gardez à l'esprit que puisque nous utilisons Vuexfire / Vuefire, nous disons que nous souhaitons nous abonner aux modifications en direct de notre requête afin que notre requête liée définisse précisément ce qui se retrouve dans notre tableau lié.

Solution n ° 1 . La pagination des charges avant / arrière et affiche une tranche horizontale de l'ensemble de données complet (notre tableau lié conserve la même taille = taille de page). Ce n'est pas ce que vous avez demandé mais pourrait être une solution préférée compte tenu des Cons d'autres solutions.

  • Avantages : Serveur: pour les grands ensembles de données, cette requête de pagination s'exécutera avec le moins de coûts et de délais.
  • Avantages : Client: conserve une petite empreinte mémoire et restitue plus rapidement.
  • Inconvénients : la pagination n'aura probablement pas l'impression de défiler. L'interface utilisateur aura probablement juste des boutons pour avancer / reculer.
  • Page suivante : récupérez l'objet doc du dernier élément de notre tableau d'état et appliquez une condition startAfter(doc) à notre requête d'affichage mise à jour qui lie notre tableau à la page suivante.
  • Page en arrière : un peu plus dur! Obtenez l'objet doc partir du premier élément de notre tableau d'état lié. Exécutez notre requête de page avec startAfter (doc), limit (1), offset (pagesize-1) et l' ordre de tri inverse . Le résultat est le doc de départ (pageDoc) de la page précédente. Utilisez maintenant startAfter(pageDoc) et l' ordre de tri et la limite de transfert (pageSize) pour relier le tableau d'état (même requête que Page Forward mais avec doc = pageDoc).

REMARQUE: Dans le cas général, je dirais que nous ne pouvons pas simplement conserver les valeurs de pageDoc des pages précédentes (pour éviter notre requête inverse) car nous traitons cela comme une liste filtrée de mise à jour en direct, donc le nombre d'éléments les restes des pages précédentes auraient pu radicalement changer depuis le défilement. Votre application spécifique ne peut pas s'attendre à ce taux de changement, donc peut-être que conserver les valeurs passées de pageDoc serait plus intelligent.

Solution n ° 2 . La pagination vers l'avant, étend la taille du résultat de la requête et du tableau lié.

  • Avantages : UX ressemble à un défilement normal depuis que notre tableau grandit.

  • Avantages : pas besoin d'utiliser l'astuce du serializer car nous n'utilisons pas startAfter() ou endBefore()

  • Inconvénients : Serveur: vous rechargez depuis Firestore l'intégralité de la baie jusqu'à la nouvelle page à chaque fois que vous vous reliez à une nouvelle page, puis obtenez des mises à jour en direct pour une baie en pleine croissance. Toutes ces lectures de doc pourraient coûter cher!

  • Inconvénients : Client: le rendu peut devenir plus lent à mesure que vous avancez, bien que le DOM fantôme puisse résoudre ce problème. L'interface utilisateur peut scintiller lorsque vous rechargez à chaque fois, donc plus de tours de magie UI nécessaires (retardez le rendu jusqu'à ce que le tableau soit entièrement mis à jour).

  • Avantages : Cela pourrait bien fonctionner si nous utilisons une fonction de défilement infini . Je devrais le tester.

  • Page Forward : Ajoutez pageSize à notre limite de requête et reliez - qui interrogera à nouveau Firestore et rechargera tout.

  • Page Backward : Soustraire pageSize de notre limite de requête et relier / recharger (ou pas!). Peut également avoir besoin de mettre à jour notre position de défilement.

Solution n ° 3 . Hybride de la solution # 1 et # 2. Nous pourrions choisir d'utiliser la liaison Vuexfire / Vuefire en direct pour seulement une tranche de notre requête / collection (comme la solution # 1) et utiliser une fonction calculée pour la concaténer avec un tableau contenant les pages de données que nous avons déjà chargées.

  • Avantages : Réduit le coût de la requête Firestore et le délai de requête, mais maintenant avec une apparence et une sensation de défilement fluide, vous pouvez donc utiliser l'interface de défilement infinie. Donnez-moi un Koolaid!
  • Inconvénients : Nous devrons essayer de garder une trace de la partie de notre tableau qui est affichée et de la rendre liée et donc mise à jour en direct.
  • Page avant / arrière: même accord que la solution n ° 1 pour lier la page de données actuelle, sauf que nous devons maintenant copier la page de données précédente dans notre tableau de données non en direct et coder une petite fonction calculée pour concat() les deux tableaux, puis liez la liste d'interface utilisateur à ce tableau calculé.

Solution # 3a Nous pouvons tricher et ne pas réellement garder les premières pages de données invisibles. Au lieu de cela, nous remplaçons simplement chaque page par un div (ou similaire) de la même hauteur;) afin que notre défilement semble avoir défilé sur la même distance. Au fur et à mesure que nous reculons, nous devrons supprimer notre div précédente page sournoise et la remplacer par les données nouvellement liées. Si vous utilisez le défilement infini, pour rendre l'UX de défilement agréable et fluide, vous devrez précharger une page supplémentaire devant ou derrière afin qu'elle soit déjà chargée bien avant de défiler jusqu'au saut de page. Certaines API de défilement infini ne prennent pas en charge cela.

La solution # 1 & # 3 a probablement besoin d'un PR Cookbook vers VueFire ou d'une belle bibliothèque MIT'd / NPM. N'importe quels preneurs?

Related