Même à l'ère des frameworks comme React et Vue, une compréhension solide de la manipulation directe du DOM reste une compétence indispensable. C'est le cœur de ce que font les frameworks en coulisses, la base pour construire des Web Components, et la seule approche pour les projets en JavaScript pur (vanilla JS). Les API DOM modernes sont étonnamment puissantes et élégantes, vous permettant de réaliser des interfaces dynamiques sans dépendances externes complexes comme jQuery.
Sélectionner des Éléments du DOM
// Pour un élément unique
const entete = document.querySelector('.header');
const boutonSoumission = document.getElementById('submit-btn');
const premierArticle = document.querySelector('article:first-of-type');
// Pour plusieurs éléments (retourne une NodeList)
const cartes = document.querySelectorAll('.card');
const liensNav = document.querySelectorAll('nav a');
// Itérer sur une NodeList
cartes.forEach(carte => {
carte.classList.add('charge');
});
// Convertir en tableau pour utiliser toutes les méthodes Array
const tableauCartes = [...document.querySelectorAll('.card')];
const cartesVisibles = tableauCartes.filter(c => !c.hidden);
Modifier les Éléments du DOM
const el = document.querySelector('.hero-title');
// Contenu textuel (sécurisé — pas d'injection HTML)
el.textContent = 'Bonjour, Monde!';
// Contenu HTML (⚠️ Risque XSS avec les entrées utilisateur)
el.innerHTML = '<strong>Bonjour</strong>, Monde!';
// Attributs
el.setAttribute('role', 'heading');
el.getAttribute('data-id');
el.removeAttribute('hidden');
// Dataset (attributs data-*)
el.dataset.userId = '123'; // Définit data-user-id="123"
console.log(el.dataset.userId); // "123"
// Classes CSS
el.classList.add('active', 'visible');
el.classList.remove('chargement');
el.classList.toggle('mode-sombre');
el.classList.contains('active'); // true/false
el.classList.replace('ancienne-classe', 'nouvelle-classe');
// Styles en ligne
el.style.color = '#6366f1';
el.style.setProperty('--accent', '#22d3ee');
Créer et Insérer des Éléments Dynamiquement
// Créer un nouvel élément
const carte = document.createElement('div');
carte.className = 'card';
carte.innerHTML = `
<h3>${titre}</h3>
<p>${description}</p>
`;
// Insérer dans le DOM
contenant.appendChild(carte); // À la fin
contenant.prepend(carte); // Au début
contenant.insertBefore(carte, elementReference); // Avant un élément spécifique
// Méthodes d'insertion modernes
element.before(nouvelElement); // Avant l'élément
element.after(nouvelElement); // Après l'élément
element.replaceWith(nouvelElement); // Remplace l'élément
// Supprimer du DOM
element.remove();
// Cloner un élément existant
const clone = modele.cloneNode(true); // true = clone en profondeur
Gérer les Événements du DOM
const bouton = document.querySelector('#submit');
// Ajouter un écouteur d'événement
bouton.addEventListener('click', (event) => {
event.preventDefault();
console.log('Cliqué!', event.target);
});
// Supprimer un écouteur d'événement (doit utiliser une fonction nommée)
function gererClic(e) { /* ... */ }
bouton.addEventListener('click', gererClic);
bouton.removeEventListener('click', gererClic);
// Événements courants
element.addEventListener('click', gestionnaire); // Clic de souris
element.addEventListener('input', gestionnaire); // Changements en temps réel dans les champs de saisie
element.addEventListener('change', gestionnaire); // La saisie perd le focus
element.addEventListener('submit', gestionnaire); // Soumission de formulaire
element.addEventListener('keydown', gestionnaire); // Touche pressée
element.addEventListener('scroll', gestionnaire); // Défilement
element.addEventListener('load', gestionnaire); // Ressource chargée
Délégation d'Événements
Au lieu d'attacher un écouteur d'événement à chaque élément enfant, il est souvent plus performant et plus flexible d'ajouter un seul écouteur au parent. Vous pouvez ensuite utiliser la propriété event.target pour déterminer quel enfant spécifique a déclenché l'événement. Cette approche est particulièrement utile pour les listes dynamiques où de nouveaux éléments sont ajoutés ou supprimés du DOM.
// ❌ Mauvaise pratique — un écouteur par élément
document.querySelectorAll('.card').forEach(carte => {
carte.addEventListener('click', gererClicCarte);
});
// ✅ Bonne pratique — un seul écouteur sur le conteneur parent
document.querySelector('.card-grid').addEventListener('click', (e) => {
const carte = e.target.closest('.card');
if (!carte) return; // Le clic n'était pas sur une carte
const id = carte.dataset.id;
gererClicCarte(id);
});
L'Élément ``
L'élément HTML <template> est un moyen puissant de stocker des fragments de contenu HTML qui ne sont pas rendus initialement sur la page, mais peuvent être clonés et utilisés ultérieurement par JavaScript. C'est idéal pour créer des composants d'interface utilisateur réutilisables de manière performante.
<!-- Modèle HTML (non rendu initialement) -->
<template id="modele-carte">
<div class="card">
<h3 class="card-title"></h3>
<p class="card-desc"></p>
</div>
</template>
<script>
const modele = document.getElementById('modele-carte');
function ajouterCarte(titre, description) {
const clone = modele.content.cloneNode(true); // true pour un clone en profondeur
clone.querySelector('.card-title').textContent = titre;
clone.querySelector('.card-desc').textContent = description;
document.querySelector('.grid').appendChild(clone);
}
</script>
Conseils de Performance pour le DOM
Optimiser les interactions avec le DOM est crucial pour des applications web fluides et réactives. Voici quelques bonnes pratiques à adopter :
- Regroupez les mises à jour du DOM — Utilisez un
DocumentFragmentou construisez des chaînes HTML complètes avant d'effectuer une seule insertion dans le DOM plutôt que des modifications individuelles. - Préférez la délégation d'événements — Cela réduit le nombre d'écouteurs d'événements et améliore la gestion des éléments dynamiques.
- Évitez le 'layout thrashing' — Ne lisez pas de propriétés de mise en page (ex:
offsetHeight) puis écrivez-en (ex:style.height) immédiatement dans une boucle. Cela force le navigateur à recalculer la mise en page de manière répétée. - Utilisez
requestAnimationFramepour toutes les mises à jour visuelles et animations, afin de synchroniser avec le cycle de rafraîchissement du navigateur. - Débrayez (debounce) les gestionnaires de défilement et de redimensionnement — Ces événements se déclenchent des dizaines de fois par seconde. Limitez leur exécution pour éviter de surcharger le processeur.
Découvrez Nos Outils JavaScript Gratuits
Minifiez et embellissez votre code JavaScript et HTML en un clin d'œil.