jQuery: insertion DOM la plus rapide?
-
02-07-2019 - |
Question
J'ai eu ce mauvais pressentiment sur la manière dont j'insère de plus grandes quantités de HTML. Supposons que nous ayons:
var html="<table>..<a-lot-of-other-tags />..</table>"
et je veux mettre cela dans
$("#mydiv")
auparavant, j'ai fait quelque chose comme
var html_obj = $(html);
$("#mydiv").append(html_obj);
Est-il exact que jQuery analyse html
pour créer des objets DOM? Eh bien, c’est ce que j’ai lu quelque part (UPDATE: je voulais dire que j’ai lu, jQuery analyse le code HTML pour créer l’arbre DOM entier à la main - c’est absurde, n'est-ce pas? , j'ai donc changé de code:
$("#mydiv").attr("innerHTML", $("#mydiv").attr("innerHTML") + html);
Se sent plus vite, n'est-ce pas? Et est-il exact que cela équivaut à:
document.getElementById("mydiv").innerHTML += html
? ou jquery fait-il des trucs coûteux en arrière-plan?
J'aimerais bien apprendre des alternatives.
La solution
innerHTML est remarquablement rapide, et dans de nombreux cas, vous obtiendrez les meilleurs résultats en définissant simplement ce paramètre (je voudrais simplement utiliser append).
Cependant, s'il y en a déjà beaucoup dans " mydiv " vous forcez alors le navigateur à analyser et à restituer tout le contenu (tout ce qui existait auparavant, ainsi que votre nouveau contenu). Vous pouvez éviter cela en ajoutant un fragment de document à " mydiv. " au lieu de cela:
var frag = document.createDocumentFragment();
frag.innerHTML = html;
$("#mydiv").append(frag);
De cette manière, seul votre nouveau contenu est analysé (inévitablement), contrairement au contenu existant.
EDIT: Mon mauvais ... J'ai découvert que innerHTML n'est pas bien pris en charge sur les fragments de document. Vous pouvez utiliser la même technique avec n'importe quel type de nœud. Pour votre exemple, vous pouvez créer le noeud de la table racine et insérer le innerHTML dans celui-ci:
var frag = document.createElement('table');
frag.innerHTML = tableInnerHtml;
$("#mydiv").append(frag);
Autres conseils
Qu'est-ce que vous essayez d'éviter? & "Un mauvais pressentiment &"; est incroyablement vague. Si vous avez entendu & "; Le DOM est lent &"; et décidé d’éviter le DOM! &, alors c’est impossible. Chaque méthode d’insertion de code dans une page, y compris innerHTML, entraîne la création d’objets DOM. Le DOM est la représentation du document dans la mémoire de votre navigateur. Vous voulez que des objets DOM soient créés.
La raison pour laquelle les gens disent & "le DOM est lent"! " Cela est dû au fait que la création d’éléments avec document.createElement()
, qui est l’interface officielle du DOM pour la création d’éléments, est plus lente que l’utilisation de la propriété innerHTML non standard dans certains navigateurs. Cela ne signifie pas que créer des objets DOM est mauvais, il est nécessaire de créer des objets DOM, sinon votre code ne ferait rien du tout.
La réponse à propos de l'utilisation d'un fragment DOM est sur la bonne voie. Si vous êtes constamment en train d'insérer des objets HTML dans le DOM, vous constaterez des améliorations de la vitesse d'utilisation du fragment. Ce post de John Resig explique assez bien: http://ejohn.org/blog/dom-documentfragments/
Le moyen le plus rapide d'ajouter des éléments
Le moyen le plus rapide d’ajouter à l’arborescence DOM consiste à mettre en mémoire tampon l’ensemble de vos ajouts dans un seul fragment DOM, puis à ajouter le fragment dom au dom.
C’est la méthode que j’utilise dans mon moteur de jeu.
//Returns a new Buffer object
function Buffer() {
//the framgment
var domFragment = document.createDocumentFragment();
//Adds a node to the dom fragment
function add(node) {
domFragment.appendChild(node);
}
//Flushes the buffer to a node
function flush(targetNode) {
//if the target node is not given then use the body
var targetNode = targetNode || document.body;
//append the domFragment to the target
targetNode.appendChild(domFragment);
}
//return the buffer
return {
"add": add,
"flush": flush
}
}
//to make a buffer do this
var buffer = Buffer();
//to add elements to the buffer do the following
buffer.add(someNode1);
//continue to add elements to the buffer
buffer.add(someNode2);
buffer.add(someNode3);
buffer.add(someNode4);
buffer.add(someN...);
//when you are done adding nodes flush the nodes to the containing div in the dom
buffer.flush(myContainerNode);
En utilisant cet objet, je peux rendre ~ 1000 éléments à l'écran ~ 40 fois par seconde dans Firefox 4.
Voici un cas d'utilisation.
Pour commencer, écrivez un script indiquant le temps nécessaire pour le faire 100 ou 1 000 fois avec chaque méthode.
Pour vous assurer que les répétitions ne sont pas optimisées (je ne suis pas un expert des moteurs JavaScript), modifiez le code HTML que vous insérez à chaque fois, par exemple, en mettant "0001" puis "0002", puis "0003". dans une certaine cellule de la table.
Je crée une chaîne géante avec, puis je l’ajoute avec jquery. Ça marche bien et vite, pour moi.
Vous dites être intéressé par des alternatives. Si vous consultez la liste des plugins jQuery liés à DOM , vous trouverez plusieurs sont dédiés à la génération programmée d’arbres DOM. Voir, par exemple, SuperFlyDom ou Créateur d’éléments DOM ; mais il y en a d'autres.