Retirer proprement un écouteur
Objectif : Installer puis retirer proprement les écouteurs du formulaire et de la liste lorsque la vue du gestionnaire est activée ou quittée.
Une vue peut être montée puis démontée au cours de la vie d’une application, par exemple lorsque vous changez d’écran. Si ses écouteurs restent attachés, ils peuvent continuer à réagir ou être installés plusieurs fois lors d’une nouvelle activation.
Vous allez donner au gestionnaire deux points d’entrée explicites : une fonction qui active la vue et une autre qui la désactive. Cette étape ne rend pas encore les tâches persistantes ; elles restent des éléments temporaires affichés dans la page.
Une fonction nommée fournit une référence stable
addEventListener associe une fonction à un événement sur un élément. Pour retirer cet écouteur avec removeEventListener, vous devez fournir le même élément, le même type d’événement et la même référence de fonction. Une fonction anonyme créée directement dans chaque appel ne vous donne pas cette référence réutilisable ; définissez donc des fonctions nommées et passez leur nom aux deux méthodes.
Installer et nettoyer les écouteurs
La page HTML reste celle du contrat. Le fichier ci-dessous est un remplacement complet de js/main.js : il sélectionne le formulaire et la liste, puis utilise des fonctions nommées pour la soumission et les actions déléguées. La fonction activerVue empêche une installation répétée ; desactiverVue retire les deux écouteurs avec les mêmes références.
const formulaire = document.querySelector("[data-formulaire]");
const champ = document.querySelector("[name='titre']");
const liste = document.querySelector("[data-liste]");
const modele = document.querySelector("[data-modele-tache]");
if (!formulaire || !champ || !liste || !modele) {
throw new Error("Un élément nécessaire au gestionnaire est absent.");
}
let prochainId = 1;
let vueActive = false;
function traiterSoumission(evenement) {
evenement.preventDefault();
const donnees = new FormData(formulaire);
const titre = String(donnees.get("titre") ?? "").trim();
if (titre === "") {
return;
}
const fragment = modele.content.cloneNode(true);
const tache = fragment.querySelector(".atelier-tache");
const texte = fragment.querySelector("[data-titre]");
const caseTache = fragment.querySelector("[data-action='basculer']");
if (!tache || !texte || !caseTache) {
throw new Error("Le modèle de tâche est incomplet.");
}
tache.dataset.id = String(prochainId);
prochainId += 1;
texte.textContent = titre;
caseTache.checked = false;
liste.append(tache);
formulaire.reset();
champ.focus();
}
function traiterActionTache(evenement) {
const cible = evenement.target;
if (!(cible instanceof Element)) {
return;
}
const commande = cible.closest("[data-action]");
const tache = cible.closest(".atelier-tache");
if (!commande || !tache || !liste.contains(tache)) {
return;
}
if (commande.dataset.action === "supprimer") {
tache.remove();
}
}
function activerVue() {
if (vueActive) {
return;
}
formulaire.addEventListener("submit", traiterSoumission);
liste.addEventListener("click", traiterActionTache);
vueActive = true;
}
function desactiverVue() {
if (!vueActive) {
return;
}
formulaire.removeEventListener("submit", traiterSoumission);
liste.removeEventListener("click", traiterActionTache);
vueActive = false;
}
function quitterPage() {
desactiverVue();
}
activerVue();
window.addEventListener("pagehide", quitterPage, { once: true });Le code réutilise le modèle fourni et affiche le titre comme du texte, sans interpréter son contenu comme du HTML. Le clic sur la liste ne supprime une ligne que si la commande trouvée est « supprimer » ; la case à cocher reste disponible, mais son basculement applicatif sera traité avec l’état dans une prochaine leçon.
Rattacher le nettoyage au cycle de vie
Au chargement du module, activerVue() attache les écouteurs une fois. L’événement de fenêtre pagehide appelle ensuite quitterPage, qui délègue le nettoyage à desactiverVue() ; le troisième argument { once: true } retire automatiquement l’écouteur de fenêtre après son déclenchement.
Dans une application qui conserve la page mais remplace ses vues, appelez desactiverVue() au démontage de cet écran, puis activerVue() lors de sa prochaine activation. Ces fonctions sont déjà disponibles dans le fichier ; le point d’entrée autonome les appelle ici au démarrage et à la sortie de la page.
À retenir
- Passez une fonction nommée à addEventListener pour conserver une référence réutilisable.
- Pour retirer un écouteur, reprenez le même élément, le même événement et la même fonction avec removeEventListener.
- Rendez l’activation idempotente : un contrôle empêche d’installer deux fois les mêmes écouteurs.
- Retirez les écouteurs lorsque la vue est démontée ou que la page est quittée.
La prochaine leçon remplacera les modifications temporaires de l’affichage par un état unique pour les tâches.