Techniques de manipulation du DOM en JavaScript
Apprenez à manipuler le DOM en JavaScript : créer, insérer, remplacer et supprimer des éléments, puis optimiser avec le batching, les fragments de document et le clonage de nœuds.
La manipulation du DOM (Document Object Model) est un aspect essentiel du développement web qui vous permet de créer des pages dynamiques et interactives en modifiant la structure, le contenu et le style du document depuis JavaScript. Ce guide commence par les techniques fondamentales pour créer, insérer, remplacer et supprimer des éléments, puis aborde les bonnes pratiques et les optimisations de performance — batching, fragments de document et clonage de nœuds — qui permettent de rendre ces changements rapides.
Si vous n'avez pas encore sélectionné d'élément, commencez par sélectionner des éléments DOM. Pour comprendre l'arbre que vous modifiez, consultez la compréhension des nœuds DOM.
Techniques fondamentales de manipulation
Chaque modification du DOM appartient à l'une des quatre catégories suivantes : créer des nœuds, les insérer, les remplacer ou les supprimer.
Créer des éléments
Utilisez document.createElement() pour construire un élément en mémoire, puis définissez son contenu et ses attributs avant de l'insérer dans la page. Un nœud que vous créez n'est pas visible tant qu'il n'est pas rattaché au document.
const card = document.createElement('div');
card.className = 'card';
card.textContent = 'Hello, DOM!';
card.setAttribute('data-role', 'greeting');
console.log(card.outerHTML);
// <div class="card" data-role="greeting">Hello, DOM!</div>Préférez textContent à innerHTML lorsque vous insérez du texte brut — c'est plus rapide et vous évite le risque de sécurité lié à l'injection de HTML non échappé.
Insérer des éléments
Une fois qu'un élément existe, rattachez-le à l'aide de l'une de ces méthodes :
parent.append(node)— ajoute le nœud comme dernier enfant (accepte également des chaînes de caractères).parent.prepend(node)— l'ajoute comme premier enfant.target.before(node)/target.after(node)— insère un frère avant ou aprèstarget.parent.appendChild(node)— l'API classique ; ajoute un seul nœud à la fin et le renvoie.parent.insertBefore(node, reference)— insèrenodeavant l'enfantreference.
const list = document.createElement('ul');
const first = document.createElement('li');
first.textContent = 'First';
list.append(first);
const second = document.createElement('li');
second.textContent = 'Second';
list.append(second);
// Put a new item before the first one.
const top = document.createElement('li');
top.textContent = 'Top';
first.before(top);
console.log(list.children.length); // 3
console.log(list.firstElementChild.textContent); // TopPour insérer une chaîne HTML à un emplacement précis sans re-analyser tout le parent, utilisez insertAdjacentHTML() :
const wrapper = document.createElement('div');
const box = document.createElement('div');
box.textContent = 'middle';
wrapper.append(box); // box must be in the tree to gain siblings
box.insertAdjacentHTML('beforebegin', '<span>before</span>');
box.insertAdjacentHTML('afterend', '<span>after</span>');
console.log(box.previousElementSibling.textContent); // before
console.log(box.nextElementSibling.textContent); // afterRemplacer et supprimer des éléments
oldNode.replaceWith(newNode)— remplaceoldNodeparnewNodeen place.element.remove()— détache l'élément du DOM.parent.replaceChild(newNode, oldNode)etparent.removeChild(child)— les équivalents plus anciens.
const parent = document.createElement('div');
const a = document.createElement('p');
a.textContent = 'old';
parent.append(a);
const b = document.createElement('p');
b.textContent = 'new';
a.replaceWith(b);
console.log(parent.innerHTML); // <p>new</p>
b.remove();
console.log(parent.innerHTML); // (empty)Les méthodes modernes (append, prepend, before, after, replaceWith, remove) sont plus lisibles que les méthodes héritées appendChild/insertBefore/replaceChild/removeChild et acceptent plusieurs nœuds et chaînes de caractères à la fois. Préférez-les en priorité ; ne revenez à l'API héritée que si vous devez prendre en charge de très anciens navigateurs.
Bonnes pratiques de manipulation du DOM
Minimiser les accès directs au DOM
L'accès au DOM peut être lent car il peut forcer le navigateur à recalculer la mise en page et à repeindre les éléments. Pour minimiser les accès directs au DOM :
- Regroupez les mises à jour du DOM au lieu d'effectuer de nombreuses petites mises à jour séparées.
- Utilisez des variables pour stocker les références aux éléments fréquemment consultés.
Optimiser la gestion des événements
Attachez les gestionnaires d'événements de manière efficace :
- Utilisez la délégation d'événements pour réduire le nombre d'écouteurs d'événements.
- Évitez d'attacher trop d'écouteurs d'événements directement aux éléments.
Nettoyer les éléments inutilisés
Supprimez les éléments qui ne sont plus nécessaires pour libérer de la mémoire et améliorer les performances :
- Utilisez les méthodes
removeChildouremovepour supprimer des éléments du DOM.
Minimiser les reflows et les repaints
Que sont les reflows et les repaints ?
- Les reflows se produisent lorsque la mise en page d'une partie de la page change, obligeant le navigateur à recalculer les positions et les tailles des éléments.
- Les repaints surviennent lorsque l'apparence visuelle des éléments change sans affecter la mise en page (par exemple, des changements de couleur).
Techniques pour minimiser les reflows et les repaints
Regrouper les modifications
Regroupez plusieurs modifications ensemble pour éviter des reflows et des repaints répétés :
<!DOCTYPE html>
<html>
<head>
<title>Batching Changes</title>
</head>
<body>
<div id="content">Original Content</div>
<button id="update">Update Content</button>
<script>
document.getElementById('update').addEventListener('click', () => {
const content = document.getElementById('content');
content.style.display = 'none'; // Hide element to batch changes
content.innerHTML = 'Updated Content';
content.style.display = 'block'; // Show element after updates
});
</script>
</body>
</html>Cet exemple montre comment regrouper les modifications apportées à un élément DOM pour minimiser les reflows et les repaints. En masquant l'élément avant d'effectuer plusieurs mises à jour, puis en l'affichant ensuite, vous évitez les reflows et les repaints intermédiaires.
Utiliser des classes CSS pour les modifications
Appliquez les modifications CSS via des classes plutôt qu'en manipulant directement les styles :
<!DOCTYPE html>
<html>
<head>
<title>Use CSS Classes</title>
<style>
.hidden { display: none; }
.highlight { color: red; font-weight: bold; }
</style>
</head>
<body>
<div id="content">Hello World</div>
<button id="toggle">Toggle Highlight</button>
<script>
document.getElementById('toggle').addEventListener('click', () => {
const content = document.getElementById('content');
content.classList.toggle('highlight');
});
</script>
</body>
</html>Cet exemple montre comment utiliser des classes CSS pour appliquer plusieurs changements de style en une seule fois, ce qui est plus efficace que de modifier des propriétés de style individuellement. Basculer une classe qui change plusieurs styles permet de réduire le nombre de reflows et de repaints.
Utiliser les fragments de document pour les performances
Qu'est-ce qu'un fragment de document ?
Un fragment de document est un conteneur léger utilisé pour regrouper un ensemble de nœuds. Il ne fait pas partie de l'arbre DOM principal, ce qui signifie que les modifications qui lui sont apportées ne déclenchent pas de reflows ni de repaints.
Lorsque vous effectuez plusieurs manipulations du DOM, utilisez DocumentFragment pour regrouper vos modifications et les ajouter au DOM en une seule opération. Cette approche minimise les reflows et les repaints, améliorant considérablement les performances.
Exemple d'utilisation des fragments de document
<!DOCTYPE html>
<html>
<head>
<title>Document Fragments</title>
</head>
<body>
<div id="list"></div>
<button id="populate">Populate List</button>
<script>
document.getElementById('populate').addEventListener('click', (event) => {
const fragment = document.createDocumentFragment();
for (let i = 1; i <= 25; i++) {
const item = document.createElement('div');
item.textContent = `Item ${i}`;
fragment.appendChild(item);
}
document.getElementById('list').appendChild(fragment);
event.target.disabled = true; // Disable the button
});
</script>
</body>
</html>Cet exemple crée 25 éléments div et les ajoute à un fragment de document. Ce n'est qu'après que tous les éléments ont été ajoutés au fragment que celui-ci est rattaché au DOM en une seule opération. Cette approche minimise les reflows et les repaints en ne mettant à jour le DOM qu'une seule fois.
Cloner des nœuds
La méthode cloneNode()
La méthode cloneNode() est utilisée pour créer une copie d'un nœud. Elle peut cloner le nœud seul ou le nœud avec tous ses enfants.
Cloner un nœud sans ses enfants
<!DOCTYPE html>
<html>
<head>
<title>Cloning Nodes</title>
</head>
<body>
<div id="original">Original Node</div>
<button id="clone">Clone Node</button>
<script>
document.getElementById('clone').addEventListener('click', () => {
const original = document.getElementById('original');
const clone = original.cloneNode(false); // Clone without children
clone.id = 'clone';
clone.textContent = 'Cloned Node';
document.body.appendChild(clone);
});
</script>
</body>
</html>Cet exemple montre comment cloner un nœud sans ses enfants à l'aide de la méthode cloneNode(false). Le nœud cloné copiera les attributs et le contenu textuel du nœud original, mais pas ses nœuds enfants.
Cloner un nœud avec ses enfants
<!DOCTYPE html>
<html>
<head>
<title>Cloning Nodes with Children</title>
</head>
<body>
<div id="original">
Original Node
<span>Child Node</span>
</div>
<button id="clone">Clone Node with Children</button>
<script>
document.getElementById('clone').addEventListener('click', () => {
const original = document.getElementById('original');
const clone = original.cloneNode(true); // Clone with children
clone.id = 'clone';
document.body.appendChild(clone);
});
</script>
</body>
</html>Cet exemple montre comment cloner un nœud ainsi que tous ses enfants à l'aide de la méthode cloneNode(true). Le nœud cloné inclura le contenu du nœud original et tous ses nœuds descendants.
Conclusion
Une manipulation efficace du DOM est essentielle pour créer des applications web performantes. Commencez par maîtriser les méthodes fondamentales pour créer, insérer, remplacer et supprimer des éléments, puis ajoutez les optimisations : regroupez vos mises à jour, préférez les classes CSS aux styles inline, utilisez DocumentFragment pour les insertions en masse, et clonez les nœuds lorsque vous avez besoin de structures répétées. Ensemble, ces techniques maintiennent la réactivité de vos pages même lorsque le DOM grossit.
Sujets connexes
- Manipulation du DOM — un parcours plus complet sur la lecture et l'écriture de l'arbre du document.
- Traverser le DOM — naviguer entre les parents, les enfants et les frères.
- Optimisation des performances du DOM — approfondir la rapidité des manipulations.
- Gestion des événements dans le DOM — connecter les interactions efficacement.