addEventListener en JavaScript : Guide Complet des Écouteurs d'Événements

addEventListener en JavaScript : Guide Complet des Écouteurs d'Événements

Comprendre addEventListener en JavaScript

La méthode addEventListener est la pierre angulaire de l'interactivité web en JavaScript. Elle permet d'attacher des fonctions qui s'exécutent en réponse à des événements utilisateur : clics, saisie clavier, scroll, soumission de formulaire, et bien d'autres.

C'est la méthode moderne et recommandée pour gérer les événements, remplaçant les anciennes approches comme onclick ou les attributs HTML inline.

Syntaxe de addEventListener

// Syntaxe complète
element.addEventListener(type, listener, options);

// Exemples basiques
const button = document.querySelector('.btn');

// Avec une fonction nommée
function handleClick(event) {
    console.log('Bouton cliqué !', event);
}
button.addEventListener('click', handleClick);

// Avec une fonction fléchée
button.addEventListener('click', (e) => {
    console.log('Cliqué !', e.target);
});

// Avec une fonction anonyme
button.addEventListener('click', function(e) {
    console.log('Cliqué !');
});

Les événements les plus utilisés

Événements de souris

ÉvénementDéclenché quand
clickClic gauche (ou tap sur mobile)
dblclickDouble clic
mouseenterLe curseur entre dans l'élément
mouseleaveLe curseur quitte l'élément
mousemoveLe curseur bouge sur l'élément
mousedownBouton de souris enfoncé
mouseupBouton de souris relâché
contextmenuClic droit

Événements de clavier

document.addEventListener('keydown', (e) => {
    console.log('Touche pressée :', e.key, e.code);

    // Raccourcis clavier
    if (e.ctrlKey && e.key === 's') {
        e.preventDefault(); // Empêche le comportement par défaut
        saveDocument();
    }

    // Touche Escape
    if (e.key === 'Escape') {
        closeModal();
    }
});

// keyup : quand la touche est relâchée
input.addEventListener('keyup', (e) => {
    if (e.key === 'Enter') {
        submitForm();
    }
});

// input : à chaque modification de la valeur
searchInput.addEventListener('input', (e) => {
    filterResults(e.target.value);
});

Événements de formulaire

const form = document.querySelector('form');

form.addEventListener('submit', (e) => {
    e.preventDefault(); // Empêche le rechargement de la page
    const formData = new FormData(form);
    // Traitement des données
});

// Focus et blur
input.addEventListener('focus', () => {
    input.classList.add('focused');
});
input.addEventListener('blur', () => {
    input.classList.remove('focused');
    validateField(input);
});

// Change (select, checkbox, radio)
select.addEventListener('change', (e) => {
    console.log('Nouvelle valeur :', e.target.value);
});

Événements de scroll et resize

// Scroll (avec debounce pour les performances)
let ticking = false;
window.addEventListener('scroll', () => {
    if (!ticking) {
        window.requestAnimationFrame(() => {
            handleScroll(window.scrollY);
            ticking = false;
        });
        ticking = true;
    }
});

// Resize
window.addEventListener('resize', () => {
    // Utiliser un debounce en production
    adjustLayout();
});

L'objet Event en détail

button.addEventListener('click', (event) => {
    // Propriétés communes
    event.type;          // 'click'
    event.target;        // L'élément qui a déclenché l'événement
    event.currentTarget; // L'élément sur lequel le listener est attaché
    event.timeStamp;     // Timestamp de l'événement

    // Méthodes importantes
    event.preventDefault();    // Empêche le comportement par défaut
    event.stopPropagation();   // Arrête la propagation (bubbling)
    event.stopImmediatePropagation(); // Arrête aussi les autres listeners

    // Propriétés de souris
    event.clientX;   // Position X dans la fenêtre
    event.clientY;   // Position Y dans la fenêtre
    event.pageX;     // Position X dans la page (avec scroll)
    event.pageY;     // Position Y dans la page
    event.button;    // 0=gauche, 1=milieu, 2=droite

    // Modificateurs
    event.ctrlKey;   // Ctrl enfoncé
    event.shiftKey;  // Shift enfoncé
    event.altKey;    // Alt enfoncé
    event.metaKey;   // Cmd (Mac) / Win (Windows) enfoncé
});

Options avancées de addEventListener

// Troisième paramètre : options
element.addEventListener('click', handler, {
    once: true,      // Se déclenche une seule fois puis se supprime
    passive: true,   // Ne peut pas appeler preventDefault() - meilleure perf
    capture: false,  // Phase de capture (false = bubbling, par défaut)
    signal: controller.signal // Pour annuler avec AbortController
});

// once: true - Parfait pour les modals, les one-time actions
button.addEventListener('click', () => {
    showWelcomeMessage();
}, { once: true });

// passive: true - Recommandé pour scroll et touch
document.addEventListener('touchstart', handleTouch, { passive: true });
document.addEventListener('wheel', handleWheel, { passive: true });

// AbortController pour nettoyer les listeners
const controller = new AbortController();

element.addEventListener('click', handler, { signal: controller.signal });
element.addEventListener('keydown', handler2, { signal: controller.signal });

// Supprimer tous les listeners d'un coup
controller.abort();

Délégation d'événements

La délégation est un pattern essentiel qui attache un seul listener sur un parent au lieu d'un listener par enfant :

// MAUVAIS : un listener par élément
document.querySelectorAll('.card').forEach(card => {
    card.addEventListener('click', handleCard); // 100 listeners !
});

// BON : délégation d'événements
document.querySelector('.card-grid').addEventListener('click', (e) => {
    const card = e.target.closest('.card');
    if (card) {
        handleCard(card);
    }
});

// Exemple concret : liste dynamique
const todoList = document.querySelector('.todo-list');

todoList.addEventListener('click', (e) => {
    // Bouton supprimer
    if (e.target.matches('.btn-delete')) {
        e.target.closest('.todo-item').remove();
    }
    // Checkbox compléter
    if (e.target.matches('.todo-checkbox')) {
        e.target.closest('.todo-item').classList.toggle('completed');
    }
});

Supprimer un écouteur d'événement

// removeEventListener nécessite une référence à la même fonction
function handleClick(e) {
    console.log('Cliqué');
}

button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick); // OK

// ATTENTION : ceci NE FONCTIONNE PAS
button.addEventListener('click', (e) => console.log('A'));
button.removeEventListener('click', (e) => console.log('A')); // FAIL - fonction différente

// Solution moderne : AbortController
const ctrl = new AbortController();
button.addEventListener('click', (e) => {
    console.log('Cliqué');
}, { signal: ctrl.signal });

// Plus tard, pour supprimer :
ctrl.abort();

Patterns pratiques courants

Debounce pour les recherches

function debounce(fn, delay = 300) {
    let timer;
    return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => fn(...args), delay);
    };
}

const searchInput = document.querySelector('#search');
searchInput.addEventListener('input', debounce((e) => {
    fetchSearchResults(e.target.value);
}, 300));

Throttle pour le scroll

function throttle(fn, limit = 100) {
    let inThrottle;
    return (...args) => {
        if (!inThrottle) {
            fn(...args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

window.addEventListener('scroll', throttle(() => {
    updateScrollProgress();
}, 50));

Détection de clic extérieur (fermer un dropdown)

const dropdown = document.querySelector('.dropdown');
const trigger = document.querySelector('.dropdown-trigger');

trigger.addEventListener('click', () => {
    dropdown.classList.toggle('open');
});

document.addEventListener('click', (e) => {
    if (!dropdown.contains(e.target) && !trigger.contains(e.target)) {
        dropdown.classList.remove('open');
    }
});

Bonnes pratiques

  • Utilisez la délégation pour les listes dynamiques et les éléments nombreux.
  • Nettoyez vos listeners avec removeEventListener ou AbortController quand les éléments sont supprimés.
  • Utilisez passive: true pour les événements scroll et touch.
  • Debounce les événements fréquents (input, resize, scroll) pour les performances.
  • Préférez les fonctions nommées aux fonctions anonymes pour faciliter le débogage.
  • N'utilisez jamais les attributs HTML inline (onclick="") en production.

Conclusion

addEventListener est la méthode fondamentale pour toute interactivité web. Maîtrisez la délégation, les options avancées et les patterns de performance pour créer des interfaces réactives et robustes.

Chez Tourak Digital, nous développons des interfaces interactives performantes et accessibles. Contactez-nous pour votre projet web.

SEO Création Web Google Ads Marketing Blog À propos
Liens rapides
Informations
Tourak Digital Group