79 votes

Des performances avec un scroll infini ou beaucoup d'éléments dom ?

J'ai une question sur un grand nombre de dom elmenets et les performances.

Disons que j'ai 6000 éléments dom sur une page et que le nombre d'éléments peut être augmenté au fur et à mesure que l'utilisateur interagit avec la page (l'utilisateur fait défiler la page pour créer un nouvel élément dom) comme twitter.

Pour améliorer les performances de la page, je ne peux penser qu'à deux choses.

  1. définir l'affichage à none pour les éléments invisibles afin d'éviter le reflux
  2. supprimer les éléments invisibles du domaine, puis les réintroduire si nécessaire.

Existe-t-il d'autres moyens d'améliorer une page comportant beaucoup d'éléments dom ?

3 votes

Le fait de définir l'affichage à none déclenche la refonte, ce qui est complètement opposé à ce que vous voulez si ce que vous voulez est d'éviter la refonte. Ne rien faire ne déclenche pas de reflux. Le fait de définir la visibilité sur hidden ne déclenche pas non plus le reflux. Cependant, il est beaucoup plus facile de ne rien faire.

3 votes

Vous devez également savoir que votre gestionnaire de fenêtres supprime déjà les pixels invisibles de l'écran pour accélérer l'interaction avec l'interface utilisateur. Si vous le faites vous-même en javascript, vous risquez de ralentir les choses au lieu de les accélérer.

0 votes

@slebetman // Quand je mets display à none, cela déclenche le reflow. C'est vrai. Mais lorsque vous faites défiler la page, cela déclenche également le reflux et le navigateur doit calculer la mise en page pour tous les éléments de la page. Je pensais que le fait de définir display none à certains des éléments de la page aiderait à réduire le temps de calcul de la mise en page.

103voto

Mutahhir Points 1090

Nous avons dû faire face à un problème similaire sur FoldingText . Au fur et à mesure que le document s'agrandissait, davantage d'éléments de ligne et d'éléments span associés étaient créés. Le moteur du navigateur semblait s'étouffer, et il fallait donc trouver une meilleure solution.

Voici ce que nous avons fait, qui peut ou non être utile à vos fins :

Visualisez la page entière comme un long document, et la fenêtre du navigateur comme l'objectif d'une partie spécifique du long document. Il suffit de montrer la partie qui se trouve dans l'objectif.

La première partie consiste donc à calculer le port de vue visible. (Cela dépend de la façon dont vos éléments sont placés, absolu / fixe / par défaut)

var top = document.scrollTop;
var width = window.innerWidth;
var height = window.innerHeight;

D'autres ressources pour trouver une fenêtre d'affichage plus compatible avec les navigateurs :

Obtenez les dimensions de la fenêtre du navigateur avec JavaScript

Méthode inter-navigateurs pour détecter le scrollTop de la fenêtre du navigateur

Deuxièmement, vous avez besoin d'une structure de données pour savoir quels éléments sont visibles dans cette zone.

Nous avions déjà mis en place un arbre de recherche binaire équilibré pour l'édition de texte, nous l'avons donc étendu pour gérer également les hauteurs de ligne, cette partie a donc été relativement facile pour nous. Je ne pense pas que vous ayez besoin d'une structure de données complexe pour gérer les hauteurs de vos éléments ; un simple tableau ou un objet peut faire l'affaire. Assurez-vous simplement de pouvoir interroger facilement les hauteurs et les dimensions. Maintenant, comment obtenir les données de hauteur pour tous vos éléments ? Une solution très simple (mais coûteuse en calcul pour un grand nombre d'éléments !)

var boundingRect = element.getBoundingClientRect()

Je parle en termes de javascript pur, mais si vous utilisez jQuery $.offset , $.position et les méthodes énumérées aquí serait très utile.

Encore une fois, l'utilisation d'une structure de données n'est importante que comme cache, mais si vous voulez, vous pouvez le faire à la volée (bien que, comme je l'ai dit, ces opérations soient coûteuses). Faites également attention à ne pas modifier les styles css et à appeler ces méthodes. Ces fonctions forcent le redessin, donc vous verrez un problème de performance.

Enfin, il suffit de remplacer les éléments hors écran par un seul, disons <div> élément dont la hauteur est calculée

  • Maintenant, vous avez des points d'appui pour tous les éléments stockés dans votre structure de données, interrogez tous les éléments qui se trouvent dans la structure de données. avant la fenêtre visible.

  • Créer un <div> avec une hauteur css définie (en pixels) à la somme des hauteurs des éléments.

  • Indiquez le nom de la classe pour que vous sachiez qu'il s'agit d'une division de remplissage.

  • Enlever tous les éléments du dom que ce div couvre

  • insérez ce div nouvellement créé à la place

Répétez l'opération pour les éléments qui se trouvent après la fenêtre visible.

Recherchez les événements de défilement et de redimensionnement. À chaque défilement, vous devrez revenir à votre structure de données, supprimer les divs de remplissage, créer les éléments qui ont été précédemment supprimés de l'écran et ajouter en conséquence de nouvelles divs de remplissage.

) Il s'agit d'une méthode longue et complexe, mais pour les documents volumineux, elle a permis d'améliorer considérablement nos performances.

en résumé

Je ne suis pas sûr de l'avoir expliqué correctement, mais l'essentiel de cette méthode est :

  • Connaître les dimensions verticales de vos éléments
  • Connaître le port de la vue défilée
  • Représenter tous les éléments hors écran avec un seul div (hauteur égale à la somme des hauteurs de tous les éléments qu'il couvre)
  • Vous aurez besoin de deux divs au total à tout moment, l'un pour les éléments situés au-dessus de la fenêtre visible, l'autre pour les éléments situés en dessous.
  • Gardez la trace du port d'affichage en écoutant les événements de défilement et de redimensionnement. Recréez les divs et les éléments visibles en conséquence

J'espère que cela vous aidera.

0 votes

// C'est logique ! Merci pour votre perspicacité !

0 votes

Pouvez-vous donner un exemple d'un cas où une structure de données complexe serait nécessaire ?

3 votes

A propos, j'ai trouvé que c'était la seule façon de gérer beaucoup d'éléments DOM tout en gardant une expérience de défilement raisonnable. En outre, la récupération de scrollTop dans le gestionnaire de défilement (jquery) ne provoque pas de redessin. En fait, il ne le fait jamais, il ne fait que vider la file d'attente des redessinages et des repeints afin que le dernier scrollTop à jour puisse être renvoyé. Je pense qu'il est déjà à jour au moment où le scrollevent est géré.

27voto

cbp Points 9676

Je n'ai pas d'expérience dans ce domaine, mais il y a de bons conseils ici : http://engineering.linkedin.com/linkedin-ipad-5-techniques-smooth-infinite-scrolling-html5

J'ai jeté un coup d'œil à Facebook et ils ne semblent pas faire quelque chose de particulier sur Firefox. Lorsque vous faites défiler la page, les éléments DOM en haut de la page ne changent pas. L'utilisation de la mémoire de Firefox grimpe jusqu'à environ 500 mégaoctets avant que Facebook ne vous permette plus de faire défiler la page.

Twitter semble être le même que Facebook.

Google Maps est une autre histoire : les tuiles de carte hors de vue sont supprimées du DOM (mais pas immédiatement).

1 votes

// Merci d'avoir pris le temps d'enquêter sur votre trouvaille. Je ferai de même bientôt.

2 votes

Il serait vraiment intéressant de voir comment Pinterest s'y prend. Ils semblent avoir compris qu'ils chargent les éléments dynamiquement lorsque vous faites défiler les pages vers le bas et vers le haut. Ils semblent toujours avoir un nombre fixe de Pins chargés sur la page d'alimentation à un moment donné.

10voto

tonix Points 2368

Nous sommes en 2019. La question est vraiment ancienne, mais je pense qu'elle est toujours pertinente et intéressante et peut-être que quelque chose a changé à partir d'aujourd'hui, car nous avons tous maintenant aussi tendance à utiliser React JS.

J'ai remarqué que la timeline de Facebook semble utiliser des grappes de contenu qui sont cachées par des display: none !important dès que le cluster est hors de vue, donc tous les éléments précédemment rendus du DOM sont conservés dans le DOM, c'est juste que ceux hors de vue sont cachés avec display: none !important . De même, la hauteur totale de la grappe cachée est fixée au parent div de la grappe cachée.

Voici quelques captures d'écran que j'ai réalisées :

enter image description here

enter image description here

enter image description here

A partir de 2019, que pensez-vous de cette approche ? De plus, pour ceux qui utilisent React, comment pourrait-on l'implémenter dans React ? Il serait formidable de recevoir vos avis et réflexions concernant ce sujet délicat.

Merci pour l'attention !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X