Les Événements en JavaScript : addEventListener
click, input, submit, délégation, propagation — gérer les interactions utilisateur
SECTION 01
addEventListener : la base
// Syntaxe : element.addEventListener(événement, callback)
const btn = document.querySelector(« #btn »);
btn.addEventListener(« click », () => );
// Plusieurs listeners sur le même élément (pas de conflit)
btn.addEventListener(« click », logClick);
btn.addEventListener(« click », sendAnalytics);
btn.addEventListener(« mouseenter », showTooltip);
N'utilise jamais les attributs HTML inline (onclick= »… ») ou les propriétés (el.onclick = …). addEventListener est la seule méthode qui permet plusieurs listeners et qui se retire proprement.
SECTION 02
L'objet event
Le callback reçoit un objet event (e) avec toutes les informations sur l'événement :
| Propriété | Rôle |
|---|---|
| e.target | L'élément cliqué (peut être un enfant) |
| e.currentTarget | L'élément qui porte le listener |
| e.preventDefault() | Empêche l'action par défaut (lien, submit…) |
| e.stopPropagation() | Empêche le bubbling vers le parent |
| e.key | Touche pressée (événements clavier) |
| e.clientX / e.clientY | Position de la souris dans le viewport |
SECTION 03
Événements souris
| Événement | Déclenché quand |
|---|---|
| click | Clic (souris ou clavier sur un bouton focusé) |
| dblclick | Double clic |
| mousedown / mouseup | Bouton enfoncé / relâché |
| mouseenter / mouseleave | Souris entre / sort de l'élément (pas de bubbling) |
| mouseover / mouseout | Comme enter/leave mais avec bubbling |
| mousemove | Souris bouge sur l'élément (très fréquent) |
| contextmenu | Clic droit |
document.addEventListener(« mousemove », (e) => );
SECTION 04
Événements clavier
| Événement | Déclenché quand | Note |
|---|---|---|
| keydown | Touche enfoncée | ✅ Le plus utilisé |
| keyup | Touche relâchée | Utile pour détecter le relâchement |
| keypress | — | ❌ Obsolète — ne plus utiliser |
document.addEventListener(« keydown », (e) => );
// Raccourcis clavier (Ctrl+S)
document.addEventListener(« keydown », (e) => );
Utilise e.key (la touche logique : « Enter », « a ») et pas e.keyCode qui est obsolète. Pour les modificateurs : e.ctrlKey, e.shiftKey, e.altKey, e.metaKey (Cmd sur Mac).
SECTION 05
Événements formulaire
| Événement | Déclenché quand | Sur |
|---|---|---|
| submit | Formulaire soumis | La balise |
| input | Valeur change (en temps réel) | input, textarea, select |
| change | Valeur change (quand le champ perd le focus) | input, textarea, select |
| focus / blur | Champ reçoit / perd le focus | Tout élément focusable |
const form = document.querySelector(« #login-form »);
form.addEventListener(« submit », (e) => );
// Recherche en temps réel
const search = document.querySelector(« #search »);
search.addEventListener(« input », (e) => );
FormData est la façon propre de récupérer toutes les valeurs d'un formulaire. Pas besoin de querySelectorAll sur chaque input. new FormData(form) collecte tout d'un coup.
SECTION 06
Propagation et bubbling
Quand tu cliques sur un élément, l'événement remonte vers le parent, puis le grand-parent, jusqu'au document. C'est le bubbling.
document.querySelector(« #parent »).addEventListener(« click », () => );
document.querySelector(« #child »).addEventListener(« click », () => );
// Clic sur le bouton → affiche :
// « Bouton cliqué »
// « Parent cliqué » ← le clic REMONTE au parent
child.addEventListener(« click », (e) => );
SECTION 07
Délégation d'événements
Au lieu de mettre un listener sur chaque élément, tu en mets un seul sur le parent. Grâce au bubbling, le parent intercepte les clics de tous ses enfants.
document.querySelectorAll(« .card .delete-btn »).forEach(btn => );
// ⚠️ Ne fonctionne pas pour les cartes ajoutées APRÈS
// ✅ Avec délégation — un seul listener sur le parent
document.querySelector(« .cards-container »).addEventListener(« click », (e) => );
Avantages de la délégation : (1) Un seul listener au lieu de N — meilleure performance. (2) Fonctionne pour les éléments ajoutés dynamiquement (pas besoin de ré-attacher). (3) closest() est la clé — il retrouve l'ancêtre qui matche.
- , fonctionne même
// pour les
const list = document.querySelector(« #todo-list »);
list.addEventListener(« click », (e) => );
SECTION 08
Supprimer un listener
// Pour retirer un listener, il faut une référence à la MÊME fonction
function handleClick()
btn.addEventListener(« click », handleClick);
btn.removeEventListener(« click », handleClick); // ✅ Même référence
// ❌ NE MARCHE PAS — fonctions anonymes différentes
btn.addEventListener(« click », () => console.log(« A »));
btn.removeEventListener(« click », () => console.log(« A »)); // ❌ Autre ref
// Option — se supprime automatiquement après 1 exécution
btn.addEventListener(« click », handleClick, );
// AbortController — retirer plusieurs listeners d'un coup
const controller = new AbortController();
btn.addEventListener(« click », fn1, );
btn.addEventListener(« mouseenter », fn2, );
input.addEventListener(« input », fn3, );
controller.abort(); // supprime les 3 listeners d'un coup
AbortController est la méthode moderne (2021+) pour gérer le cycle de vie des listeners. Un seul abort() nettoie tout — très utile dans les composants et les SPA.
SECTION 09
Erreurs fréquentes
| Erreur | Problème | Solution |
|---|---|---|
| Script chargé avant le DOM | querySelector retourne null | defer sur le script ou DOMContentLoaded |
| Appeler la fonction au lieu de la passer | addEventListener(« click », fn()) exécute fn immédiatement | Passer la référence : fn sans () |
| Un listener par item dynamique | Ne marche pas pour les éléments ajoutés après | Utiliser la délégation |
| Pas de preventDefault sur submit | La page se recharge | e.preventDefault() en premier |
| Vouloir retirer un listener anonyme | Impossible sans référence | Nommer la fonction ou utiliser AbortController |
SECTION 10
Questions fréquentes
🌳 Manipuler le DOM
➡️ Fonctions fléchées
🌐 Fetch API
🔤 let, const, var
🔁 Boucles
⚡ Cours JavaScript complet
🏠 Hub Programmation
Référence : MDN addEventListener
