web-dev-qa-db-fra.com

AngularJS: répétition virtuelle avec rangée à différentes hauteurs

Je construis une application hybride utilisant ionic et AngularJS (matériau AngularJS). Cette application a également un chat intégré construit avec Node.js et socket.io.

J'ai le problème maintenant qu'avec seulement 200 messages, l'application devient très lente pour charger tous les messages (200 ms dans le navigateur -> 4sec dans l'application, même avec CrossWalk, et avec piste par message.id) et en tapant également dans la zone de texte. insérer le message est ralenti.

J'ai deux solutions pour résoudre ce problème:

  1. Répétition virtuelle (md-virtual-repeat)
  2. Défilement infini (ion-infinite-scroll)

1) Je pense que la répétition virtuelle serait la meilleure solution (je l’ai déjà implémentée sur une autre page et elle fait défiler 1500 éléments comme un charme) mais le problème est que les messages peuvent avoir différentes hauteurs en fonction de leur longueur et de md-virtual- Les exigences de répétition sont que tous les éléments doivent avoir la même hauteur pour fonctionner.

2) Alors peut-être que nous pouvons passer à la méthode de défilement infini mais le problème est maintenant que le faire avec la directive ion-infinite-scroll devient un peu délicat, car une discussion doit déclencher le loadMore () pour atteindre le sommet et non le bas .

Ma question est donc la suivante: Quelqu'un at-il une solution de contournement pour avoir une répétition régulière/rapide dans un chat en utilisant ou une directive de répétition virtuelle qui peut gérer différentes hauteurs ou un défilement infini qui fonctionne à la Haut ?

22
Matteo Cardellini

Des listes de défilement efficaces comme md-virtual-repeat ou collection-repeat doivent connaître la hauteur de chaque élément pour fonctionner. C’est parce qu’ils ont besoin de connaître la position du défilement, par exemple pour afficher une barre de défilement ou pour pouvoir sauter des images pour des mouvements rapides de balayage. La position de défilement elle-même ne peut être trouvée que si vous savez à la fois combien a été fait défiler (nous avons besoin de la hauteur des éléments ci-dessus) et combien il reste à parcourir (nous avons besoin de la hauteur des éléments ci-dessous).

Ce que vous pouvez faire est d'utiliser une usine pour calculer la hauteur de chaque élément avant de l'injecter dans la boucle. Cela peut être fait en créant un conteneur avec les mêmes propriétés que le conteneur cible (par exemple, les classes CSS), en ajoutant les éléments récemment chargés, en calculant leur hauteur (à l'aide de element.offsetHeight), puis en supprimant le conteneur après.

Sachez que ceci est assez lourd et entraînera probablement un léger pic de décalage.

2
Iso

Quelques choses que vous pourriez essayer d'accélérer. 

On pourrait utiliser quelque chose comme quick-ng-repeat: https://github.com/allaud/quick-ng-repeat au lieu de la fonction angular intégrée js ng-repeat

Une autre solution consisterait à utiliser one time binding chaque fois que possible pour empêcher angular de rechercher constamment des modifications pendant chaque cycle de résumé: https://docs.angularjs.org/guide/expression#one-time-binding

Et bien sûr, si cela est possible, essayez d’utiliser l’option de profil d’outil de développeur de chrome pour déterminer les fonctions qui ralentissent l’application; )

PS: Peut-être vaut-il la peine de consulter ce fil pour voir comment le défilement infini inverse peut être mis en œuvre: Implémentation d'un défilement infini inverse à l'aide de la directive ngInfiniteScroll dans AngularJS

2
Chanthu

Je pense que la directive ionique collection-repeat pourrait être ce que vous cherchez. 

collection-repeat permet à une application d'afficher d'énormes listes d'éléments beaucoup plus performant que ng-repeat. Il ne restitue dans le DOM que le nombre les éléments tels qu'ils sont actuellement visibles. Cela signifie que sur un écran de téléphone que peut contenir huit éléments, seuls les huit éléments correspondant au défilement actuel la position sera rendue.

1
nicfo

L'utilisation de liants séparés, tels que des rivets, pourrait constituer une bonne solution, car elle est facile à intégrer et permet de créer des boucles pour chaque boucle.

1
krishnakumar sekar

Avez-vous examiné la solution React.js? Il utilise un DOM virtuel qui rend la mise à jour de longues listes plus efficace.

Il y a un repo open-source sur GitHub qui mélange Angular et React, appelé ngReact.

aperçu: http://ngreact.github.io/ngReact/

docs: http://ngreact.github.io/ngReact/docs/ngReact.html

repo: https://github.com/ngReact/ngReact

J'espère que cela t'aides.

1
Matt

Regardez angular-vs-repeatangular-vs-repeat

Démo: démo

J'utilise la longueur de ligne pour calculer la hauteur des éléments.

C'est une méthode très approximative. Dans notre application, nous savons qu'un caractère anglais avec une taille de police de 15px aura une largeur d'environ 6,7px (c'est bien, si vous utilisez une police monospace, mais ce n'est pas notre cas). Nous savons aussi toujours La largeur de chaque segment et la hauteur d'une ligne de texte. .

0
Mikhail Kostin