Gestione degli eventi nel DOM
Gestione eventi JavaScript nel DOM: addEventListener, removeEventListener, oggetto event, preventDefault, bubbling e delega degli eventi con esempi.
Introduzione agli eventi JavaScript
Gli eventi JavaScript sono azioni o occorrenze che si verificano nel browser — un clic, la pressione di un tasto, il completamento del caricamento di una pagina — che il codice può rilevare e a cui può rispondere. Reagire agli eventi è ciò che trasforma una pagina statica in un'applicazione interattiva.
Questo capitolo tratta i tre modi per registrare i gestori di eventi, i tipi di eventi più comuni, l'oggetto event che ogni gestore riceve, il modo in cui gli eventi si propagano attraverso il DOM (bubbling e capturing) e i pattern che mantengono le pagine ricche di eventi veloci e prive di memory leak.
Tre modi per gestire gli eventi
Prima di esaminare eventi specifici, è utile sapere che esistono tre modi distinti per collegare un gestore. Sono elencati dal più vecchio al più flessibile.
| Approccio | Esempio | Gestori multipli? | Consigliato |
|---|---|---|---|
| Attributo HTML inline | <button onclick="doX()"> | No | No — mescola markup e logica |
| Proprietà DOM | element.onclick = fn | No (l'ultimo vince) | Solo per casi semplici |
addEventListener() | element.addEventListener("click", fn) | Sì | Sì — lo standard moderno |
<button id="propBtn">Click me</button>
<script>
const btn = document.getElementById("propBtn");
// 1. DOM property — assigning again overwrites the previous handler
btn.onclick = function () {
alert("Handled by the onclick property");
};
// 2. addEventListener — adds without overwriting; you can attach many
btn.addEventListener("click", function () {
console.log("Also handled by addEventListener");
});
</script>Entrambi i gestori sopra vengono eseguiti a un clic. Se si assegna btn.onclick una seconda volta, la prima assegnazione viene persa silenziosamente — motivo principale per cui addEventListener() è preferito. Il resto di questo capitolo usa addEventListener().
Eventi comuni in JavaScript
Evento click
L'evento click si attiva quando l'utente preme e rilascia il pulsante principale del mouse (o tocca, su dispositivi touch) su un elemento. È l'evento più frequentemente utilizzato.
<button id="clickButton">Click Me</button>
<script>
document.getElementById("clickButton").addEventListener("click", function () {
alert("Button was clicked!");
});
</script>In questo esempio, viene aggiunto un listener a un pulsante con ID clickButton. Quando il pulsante viene cliccato, apparirà un alert con il messaggio "Button was clicked!".
Evento mouseover
L'evento mouseover si attiva quando il puntatore del mouse entra su un elemento. (La sua controparte, mouseout, si attiva quando il puntatore lascia l'elemento.)
<p id="mouseoverText">Hover over me!</p>
<script>
document.getElementById("mouseoverText").addEventListener("mouseover", function () {
this.style.color = "red";
});
</script>In questo esempio, viene aggiunto un listener a un paragrafo con ID mouseoverText. Quando il mouse passa sopra il paragrafo, il colore del testo cambia in rosso.
Evento keydown
L'evento keydown si attiva quando l'utente preme un tasto mentre un elemento è focalizzato. Il gestore riceve un oggetto event la cui proprietà event.key contiene il valore del tasto.
<input type="text" id="inputField" placeholder="Type something..." />
<script>
document.getElementById("inputField").addEventListener("keydown", function (event) {
alert(`Key pressed: ${event.key}`);
this.value = '';
});
</script>In questo esempio, viene aggiunto un listener a un campo di input con ID inputField. Quando viene premuto un tasto mentre il campo di input è focalizzato, il tasto premuto viene mostrato in un alert.
L'oggetto event
Ogni gestore viene chiamato con un solo argomento: l'oggetto event. Descrive cosa è accaduto ed espone metodi per controllare l'evento. I membri più utili sono:
event.target— l'elemento su cui l'evento ha avuto origine (ad es. il pulsante esatto cliccato).event.currentTarget— l'elemento a cui è collegato il listener. All'interno di una funzione regolare coincide conthis.event.type— il nome dell'evento, ad esempio"click".event.preventDefault()— annulla l'azione predefinita del browser (seguire un link, inviare un form).event.stopPropagation()— impedisce all'evento di continuare a risalire nel DOM.
<a id="link" href="https://www.w3docs.com">Visit W3docs</a>
<script>
document.getElementById("link").addEventListener("click", function (event) {
event.preventDefault(); // stop the browser from navigating away
console.log("type:", event.type); // "click"
console.log("target id:", event.target.id); // "link"
});
</script>Qui preventDefault() impedisce alla pagina di navigare, in modo da poter eseguire la propria logica — un pattern comune per le single-page app e la validazione personalizzata dei form.
All'interno di una arrow function, this non viene riassegnato all'elemento. Usa event.currentTarget (o una function normale) quando hai bisogno di un riferimento all'elemento su cui si trova il listener. Vedi arrow functions rivisitate per sapere perché.
Aggiunta di listener agli eventi
Il metodo addEventListener()
Il metodo addEventListener() collega un gestore di eventi a un elemento senza sovrascrivere i gestori esistenti. Ciò significa che puoi collegare più listener — anche per lo stesso tipo di evento — a un singolo elemento. La sua firma è element.addEventListener(type, handler, options), dove options consente di affinare il comportamento (once, capture, passive).
<button id="multiEventButton">Click or Hover</button>
<script>
const button = document.getElementById("multiEventButton");
button.addEventListener("click", function () {
alert("Button clicked!");
});
button.addEventListener("mouseover", function () {
button.style.backgroundColor = "lightblue";
});
</script>In questo esempio, vengono aggiunti due listener al pulsante con ID multiEventButton. Un listener attiva un alert quando il pulsante viene cliccato, e l'altro cambia il colore di sfondo del pulsante quando il mouse passa sopra.
Usa addEventListener() per collegare più listener allo stesso elemento senza sovrascrivere i gestori esistenti.
Rimozione di listener dagli eventi
Il metodo removeEventListener()
Il metodo removeEventListener() rimuove un gestore collegato con addEventListener(). L'aspetto importante: è necessario passare esattamente la stessa referenza alla funzione aggiunta, motivo per cui sono necessarie funzioni con nome per rimuovere un listener in seguito.
<button id="removeEventButton">Click Me</button>
<script>
function showAlert() {
alert("This will be removed after first click");
}
const button = document.getElementById("removeEventButton");
button.addEventListener("click", showAlert);
button.addEventListener("click", function () {
button.removeEventListener("click", showAlert);
});
</script>In questo esempio, viene aggiunto al pulsante con ID removeEventButton un listener che attiva un alert. Un altro listener viene aggiunto per rimuovere il listener dell'alert dopo il primo clic. Nota che removeEventListener richiede un riferimento allo stesso identico oggetto funzione usato in addEventListener. È per questo che le funzioni anonime non possono essere rimosse in seguito — ogni dichiarazione crea un nuovo oggetto funzione distinto.
Sfrutta la delega degli eventi per prestazioni migliori, specialmente quando si lavora con un gran numero di elementi figli.
Propagazione e delega degli eventi
Quando un evento si attiva su un elemento, non si ferma lì. Per impostazione predefinita viaggia in due fasi: prima il capturing (dall'alto del DOM fino al target), poi il bubbling (dal target risalendo fino alla radice). La maggior parte dei gestori viene eseguita durante la fase di bubbling, motivo per cui un clic su un pulsante raggiunge anche un listener click sul <div> genitore.
Questo bubbling abilita la delega degli eventi: invece di collegare un listener a ogni figlio, si collega un listener a un genitore comune e si legge event.target per scoprire quale figlio è stato effettivamente cliccato.
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
<script>
// One listener handles clicks on any current OR future <li>
document.getElementById("menu").addEventListener("click", function (event) {
if (event.target.tagName === "LI") {
console.log("You clicked:", event.target.textContent);
}
});
</script>Un singolo listener su <ul> gestisce ogni <li>, inclusi quelli aggiunti alla lista in seguito — molto più efficiente che collegare ogni elemento individualmente. Per un approfondimento sulle fasi e stopPropagation(), vedi bubbling e capturing.
Best practice
Usa la delega degli eventi
Aggiungi un singolo listener a un elemento genitore per gestire gli eventi di tutti gli elementi figli. Questo migliora le prestazioni e riduce il numero di listener.
Evita le funzioni anonime per i gestori di eventi
L'utilizzo di funzioni con nome per i gestori di eventi semplifica la loro rimozione in seguito e migliora la leggibilità del codice.
Rimuovi i listener non più necessari
Assicurati che i listener vengano rimossi quando non sono più necessari per evitare memory leak e migliorare le prestazioni.
Minimizza il numero di listener
Collega i listener a elementi di livello superiore invece che a numerosi elementi individuali per ridurre l'uso della memoria e migliorare le prestazioni.
Usa l'opzione once in addEventListener
Utilizza l'opzione once per rimuovere automaticamente il listener dopo che è stato attivato una volta, prevenendo potenziali memory leak.
button.addEventListener("click", function handler() {
console.log("Triggered once");
}, { once: true });Usa preventDefault e stopPropagation in modo appropriato
Usa event.preventDefault() e event.stopPropagation() con giudizio per controllare il comportamento degli eventi senza interferire con altri gestori.
Applica il debounce o il throttle ai gestori di eventi
Usa tecniche di debouncing o throttling per ottimizzare le prestazioni dei gestori di eventi attivati di frequente, come gli eventi scroll o resize.
Conclusione
Padroneggiare gli eventi JavaScript è fondamentale per creare applicazioni web dinamiche e interattive. Comprendendo come usare eventi come click, mouseover e keydown, e come aggiungere e rimuovere listener con addEventListener() e removeEventListener(), puoi migliorare significativamente le interazioni degli utenti nelle tue pagine web.