eleydet, tu poses une très bonne question 
innerHTML a essentiellement 4 problèmes.
1. L’ambigüité : rien ne nous empêche de passer du code HTML mal construit. Le navigateur compense alors comme il peut, ce qui introduit potentiellement des erreurs difficiles à détecter. De plus, les mécanismes de correction de code HTML ne sont pas standardisés, et peuvent varier selon les navigateurs.
2. La sécurité : c’est le point expliqué dans l’article MDN que NoSmoking et moi-même avons lié, je ne reviens pas dessus.
3. La corruption du DOM. Ce problème est plus subtil et moins connu. Ça se produit quand on écrit .innerHTML +=. Un exemple :
1 2 3
| <div id="exemple">
<button>Cliquez là</button>
</div> |
1 2 3 4
| let divExemple = document.getElementById("exemple");
divExemple.querySelector("button").addEventListener("click", function () {
alert("Vous avez cliqué sur le bouton");
}); |
Supposons que je veuille ajouter une balise dans la div #exemple en utilisant innerHTML :
divExemple.innerHTML += "<p>Du texte en plus</p>";
Cette instruction se décompose comme suit :
1 2 3
| let html = divExemple.innerHTML;
html = html + "<p>Du texte en plus</p>";
divExemple.innerHTML = html; |
Le contenu entier de la div va être recréé. L’ancien <button> est supprimé, et un nouveau est recréé à partir de sa représentation HTML textuelle. Ce n’est plus le même élément DOM, et les références sont brisées, en particulier les gestionnaires d’évènements qui y étaient attachés. Dans mon exemple, le gestionnaire de "click" ne fonctionnera plus.
4. La performance : passer une chaîne HTML sera toujours moins performant qu’utiliser les méthodes du DOM (createElement, append*, insert*), car le moteur JS est obligé de faire appel à l’analyseur HTML du navigateur.
Bien qu’il ne faille pas chercher la performance à tout prix, ça reste une chose importante à considérer. On s’épargne de la réécriture de code en fin de projet si on a utilisé le DOM dès le départ.
Du fait de sa popularité, innerHTML pose encore un cinquième problème : il cause du tort à la communauté JavaScript. Je vais m’expliquer.
innerHTML est une solution de facilité, car il faut reconnaître que c’est fastidieux de construire un fragment HTML en utilisant uniquement les méthodes du DOM. Après tout, c’est pour ça que les frameworks existent.
(Petite note : bien que jQuery soit optimisé avec soin, il est aussi parfois obligé de faire appel à innerHTML au lieu des méthodes du DOM. Tout dépend de comment on l’utilise. Comme en JS vanilla, il y a aussi de bonnes et de mauvaises pratiques avec jQuery.)
Ça irait encore si on n’utilisait innerHTML par flemme, que pour du prototypage et des petits projets. Mais c’est plus insidieux quand ceux et celles qui transmettent le savoir ont la flemme d’expliquer, et conseillent innerHTML aux débutants. Ainsi, la mauvaise pratique se répand.
En fait, ce n’est pas beaucoup plus compliqué de parler de textContent qui répond souvent au besoin, ou bien de insertAdjacentHTML. Ce dernier ne résoud pas tous les problèmes, mais il est déjà plus performant, et il ne corromp pas le DOM.
Par honnêteté, abordons les cas légitimes d’utilisation de innerHTML :
Pour vider un élément ?
Comme l’a écrit NoSmoking, ainsi que l’auteur de ce billet de blog, ce n’est pas performant.
D’autre part, en regardant le code de jQuery, on trouve ceci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| empty: function() {
var elem,
i = 0;
for ( ; ( elem = this[ i ] ) != null; i++ ) {
if ( elem.nodeType === 1 ) {
// Prevent memory leaks
jQuery.cleanData( getAll( elem, false ) );
// Remove any remaining nodes
elem.textContent = "";
}
}
return this;
}, |
A priori, les devs de jQuery ont jugé que elem.textContent = "" était le plus efficace. Je leur fais confiance.
pour sérialiser un fragment de document, et le sauvegarder, par exemple dans le localStorage, ou encore l’envoyer vers le serveur.
let serializedHtml = element.innerHTML;
On l’utilise alors en lecture, et uniquement en lecture ! Si on a besoin de ré-injecter le code plus tard, on utilisera alors insertAdjacentHTML.
Partager