En pratique, quels sont les avantages de l'utilisation de createElement par rapport à innerHTML? Je pose la question parce que je suis convaincu que l’utilisation de innerHTML est plus efficace en termes de performances et de lisibilité / maintenabilité du code, mais mes coéquipiers ont opté pour l’option createElement en tant qu’approche de codage. Je veux juste comprendre comment createElement peut être plus efficace.
Réponses
Trop de publicités?Il y a plusieurs avantages à l'utilisation d' createElement
au lieu de modifier innerHTML
(plutôt que de simplement jeter ce qui existe déjà et de le remplacer) en plus de la sécurité, comme Pekka déjà mentionné:
Préserve les références à des éléments du DOM lors de l'ajout d'éléments
Lorsque vous ajouter (ou modifier) innerHTML
, tous les nœuds DOM l'intérieur de cet élément doivent être ré-analysée et recréé. Si vous avez enregistré toutes les références à des nœuds, ils seront inutiles, car ils ne sont pas ceux qui font preuve de plus.
Préserve les gestionnaires d'événements attaché à aucun des éléments du DOM
C'est juste un cas particulier (bien que la commune) de le dernier. Paramètre innerHTML
ne sera pas automatiquement de rattacher les gestionnaires d'événements pour les nouveaux éléments qu'il crée, de sorte que vous auriez à garder une trace de vous-même et de les ajouter manuellement. Événement délégation peut éliminer ce problème dans certains cas.
Pourrait être plus simple, plus rapide dans certains cas
Si vous faites beaucoup d'ajouts, vous ne voulez certainement pas à garder la réinitialisation innerHTML
parce que, bien que plus rapides pour de simples changements, à plusieurs reprises ré-analyse et création d'éléments serait plus lent. La façon de se déplacer qui est de construire le code HTML dans une chaîne et définissez innerHTML
une fois lorsque vous avez terminé. Selon la situation, la manipulation de la chaîne pourrait être plus lente que la simple création d'éléments et en les ajoutant.
En outre, la manipulation de la chaîne de code peut être plus compliqué (surtout si vous voulez être sûr).
Voici une fonction que j'utilise parfois qu'il est plus pratique d'utiliser createElement
.
function isArray(a) {
return Object.prototype.toString.call(a) === "[object Array]";
}
function make(desc) {
if (!isArray(desc)) {
return make.call(this, Array.prototype.slice.call(arguments));
}
var name = desc[0];
var attributes = desc[1];
var el = document.createElement(name);
var start = 1;
if (typeof attributes === "object" && attributes !== null && !isArray(attributes)) {
for (var attr in attributes) {
el[attr] = attributes[attr];
}
start = 2;
}
for (var i = start; i < desc.length; i++) {
if (isArray(desc[i])) {
el.appendChild(make(desc[i]));
}
else {
el.appendChild(document.createTextNode(desc[i]));
}
}
return el;
}
Si vous l'appelez comme ceci:
make(["p", "Here is a ", ["a", { href:"http://www.google.com/" }, "link"], "."]);
vous obtenez l'équivalent de ce code HTML:
<p>Here is a <a href="http://www.google.com/">link</a>.</p>
L'utilisateur bobince met un certain nombre d'inconvénients, très, très bien dans sa critique de jQuery.
... De Plus, vous pouvez faire un div en disant: $("+message+") au lieu d'avoir de la boue autour de document.createElement('div') et les nœuds de texte. Hourra! Seulement... accrocher. Vous n'avez pas échappé que HTML, et ont probablement juste de créer un " cross-site-scripting trou de sécurité, que du côté client, cette fois. Et après vous avais passé tellement de temps de nettoyage de votre PHP pour utiliser htmlspecialchars sur le côté serveur, trop. Quelle honte. Ah bien, personne ne se soucie vraiment de l'exactitude ou de sécurité, ou le font-ils?
jQuery n'est pas entièrement à blâmer pour cela. Après tout, la propriété innerHTML a été d'environ pendant des années, et déjà prouvé plus en plus populaire que les DOM. Mais la bibliothèque n'est certainement encourager un style de codage.
Comme pour la performance: InnerHTML est très certainement va être plus lent, car il doit être analysée et convertie en éléments DOM (peut-être à l'aide de l' createElement
méthode).
InnerHTML est plus rapide dans tous les navigateurs selon les quirksmode de référence fournis par @Pointu.
Comme pour la lisibilité et la facilité d'utilisation, vous me trouverez en choisissant innerHTML
sur createElement
n'importe quel jour de la semaine dans la plupart des projets. Mais comme vous pouvez le voir, il ya beaucoup de points parlant createElement
.
Alors qu' innerHTML
peut être plus rapide, je ne pense pas que c'est de mieux en termes de lisibilité ou d'entretien. Il peut être plus courte pour tout mettre dans une seule chaîne, mais plus court code n'est pas toujours nécessairement plus facile à gérer.
La concaténation de chaîne ne vient pas de l'échelle de la dynamique des éléments du DOM doivent être créés comme la plus " et de citer des ouvertures et fermetures devient difficile de suivre. Considérez ces exemples:
L'élément obtenu est un div avec deux travées internes dont le contenu est dynamique. L'un des noms de classe (guerrier) à l'intérieur de la première travée est également dynamique.
<div>
<span class="person warrior">John Doe</span>
<span class="time">30th May, 2010</span>
</div>
Assumer les variables suivantes sont déjà définis:
var personClass = 'warrior';
var personName = 'John Doe';
var date = '30th May, 2010';
Juste en utilisant innerHTML et piler le tout dans une seule chaîne de caractères, on obtient:
someElement.innerHTML = "<div><span class='person " + personClass + "'>" + personName + "</span><span class='time'>" + date + "</span></div>";
Le ci-dessus gâchis peuvent être nettoyés avec de l'aide de la chaîne de remplacements pour éviter l'ouverture et la fermeture des chaînes de tous les temps. Même pour de simples remplacements de texte, je préfère utiliser l' replace
au lieu de concaténation de chaîne.
C'est une simple fonction qui prend un objet de clés et de valeurs de remplacement et les remplace dans la chaîne. Il suppose que les touches sont préfixés avec $
pour désigner ils sont d'une valeur particulière. Il ne fait pas s'échapper ou à manipuler les cas limites, $
apparaît dans la valeur de remplacement, etc.
function replaceAll(string, map) {
for(key in map) {
string = string.replace("$" + key, map[key]);
}
return string;
}
var string = '<div><span class="person $type">$name</span><span class="time">$date</span></div>';
var html = replaceAll(string, {
type: personClass,
name: personName,
date: date
});
someElement.innerHTML = html;
Cela peut être amélioré en séparant les attributs de texte, etc. lors de la construction de l'objet pour obtenir plus de contrôle par programmation sur l'élément de construction. Par exemple, avec MooTools, nous pouvons passer propriétés de l'objet sur une carte. C'est certainement plus facile à gérer, et je dirais bien plus lisible. jQuery 1.4 utilise une syntaxe similaire à passer d'une carte pour l'initialisation des objets DOM.
var div = new Element('div');
var person = new Element('span', {
'class': 'person ' + personClass,
'text': personName
});
var when = new Element('span', {
'class': 'time',
'text': date
});
div.adopt([person, when]);
Je ne dirais pas de la pure DOM approche ci-dessous pour être plus lisible que ceux ci-dessus, mais il est certainement plus facile à gérer parce que nous n'avons pas à garder une trace de l'ouverture/fermeture des guillemets et de nombreux signes plus.
var div = document.createElement('div');
var person = document.createElement('span');
person.className = 'person ' + personClass;
person.appendChild(document.createTextNode(personName));
var when = document.createElement('span');
when.className = 'date';
when.appendChild(document.createTextNode(date));
div.appendChild(person);
div.appendChild(when);
Le plus lisible version serait le plus susceptible de résulter de l'utilisation une sorte de JavaScript de templating.
<div id="personTemplate">
<span class="person <%= type %>"><%= name %></span>
<span class="time"><%= date %></span>
</div>
var div = $("#personTemplate").create({
name: personName,
type: personClass,
date: date
});