Di seguito sono riportati alcuni esempi che potrebbero aiutare le persone a comprendere e risolvere meglio i propri problemi.
TL; DR
on*
gestori di eventi (ad es. onclick
attributo su un elemento pulsante): restituire false per annullare l'evento
addEventListener
è un'API diversa, i valori di ritorno (ad esempio false
) vengono ignorati: use event.preventDefault()
.
onclick="<somejs>"
ha la sua potenziale confusione perché <somejs>
è avvolto nel corpo di una funzione onclick.
- Utilizza l'
getEventListeners
API devtools del browser per vedere come appare il tuo listener di eventi per risolvere i problemi se il tuo gestore di eventi non si comporta come previsto.
Esempio
Questo esempio è specifico per l' click
evento con un <a>
collegamento ... ma può essere generalizzato per la maggior parte dei tipi di evento.
Abbiamo un'ancora (collegamento) con la classe js-some-link-hook
che vogliamo aprire come modale e impedire che avvenga la navigazione della pagina.
Gli esempi seguenti sono stati eseguiti in Google Chrome (71) su MacOS Mojave.
Uno dei principali problemi è presumere che onclick=functionName
sia lo stesso comportamento dell'usoaddEventListener
Supponiamo di avere un anchor tag (link) che vogliamo gestire con javascript quando javascript è abilitato. Non vogliamo che il browser segua il collegamento quando viene cliccato (comportamento "Impedisci predefinito").
<a href="https://www.example.com/url/to/go/to/when/no/javascript"
class="js-some-link-hook">click me!</a>
attributo onclick
function eventHandler (event) {
alert('eventHandler ran');
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.setAttribute('onclick', eventHandler);
}
addEventListenerToElement();
Quindi esegui nella console devtools del browser:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener);
... e vedi:
function onclick(event) {
function eventHandler (event) {alert('eventHandler ran'); return false;}
}
Questo non funziona affatto. Quando si utilizza onclick=
la funzione del gestore è racchiusa in un'altra funzione.
Puoi vedere che la mia definizione di funzione è inclusa ma non chiamata perché ho specificato il riferimento alla funzione senza richiamarlo. vale a dire che dobbiamo onclick="functionName()"
non onclick="functionName"
fare in modo functionName
viene eseguito quando l'elemento viene cliccato.
Inoltre puoi vedere che anche se la mia funzione è stata chiamata e la mia funzione ha restituito false ... la onclick
funzione non restituirebbe quel valore falso ... che è richiesto per 'annullare' l'evento.
Per risolvere questo problema, possiamo impostare onclick
su be return myHandlerFunc();
che garantisce che onclick
restituisca il valore restituito (false) da myHandlerFunc
.
Potresti anche rimuovere return false;
da myHandlerFunc
e modificare onclick
in essere, myHandlerFunc(); return false;
ma questo ha meno senso poiché probabilmente vorrai mantenere la logica insieme nella tua funzione gestore.
Nota quando si imposta onclick
con javascript , quando si sta impostando onclick
direttamente in html piuttosto che con javascript (come i miei esempi), il onclick
valore dell'attributo è di tipo stringa e tutto funziona. Se stai impostando onclick
usando javascript, devi prestare attenzione al tipo. Se dici element.setAttribute('onclick', myHandlerFunc())
myHandlerFunc
che verrà eseguito in questo momento e il risultato verrà memorizzato nell'attributo ... anziché essere eseguito a ogni clic. Invece dovresti assicurarti che il valore dell'attributo sia impostato come una stringa. element.setAttribute('onclick', 'return myHandlerFunc();')
Ora che vediamo come funziona, possiamo modificare il codice per fare quello che vogliamo. Strano esempio a scopo illustrativo (non utilizzare questo codice):
function eventHandler (e) {
alert('eventHandler ran');
console.log(e);
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.setAttribute('onclick', 'return ('+eventHandler+')(event);');
}
addEventListenerToElement();
Vedete, abbiamo racchiuso la nostra definizione di funzione eventHandler in una stringa. Nello specifico: una funzione autoeseguibile con un'istruzione return in primo piano.
Di nuovo nella console di chrome devtools:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener);
...Spettacoli:
function onclick(event) {
return (function eventHandler (e) {
alert('eventHandler ran');
console.log(e);
return false;
})(event);
}
... quindi sì, dovrebbe funzionare. Abbastanza sicuro, se clicchiamo sul collegamento otteniamo l'avviso e chiudendo l'avviso la pagina non si sposta da nessuna parte né si aggiorna.
Un'altra nota su onclick
... Se vuoi ricevere e utilizzare il event
parametro al momento dell'evento, dovresti notare che si chiama "evento". È possibile accedervi all'interno del gestore utilizzando il nome event
(disponibile tramite l' onclick
ambito della funzione padre ). Oppure puoi costruire il tuo gestore da prendere event
come parametro (meglio per i test) ... ad es. onclick="return myEventHandler(event);"
O come vedi nell'esempio precedente.
addEventListener
function eventHandler (ev) {
alert('eventHandler ran');
console.log(ev);
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();
strumenti di sviluppo del browser:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener);
risultato:
function eventHandler (ev) {
alert('eventHandler ran');
console.log(ev);
return false;
}
Quindi puoi già vedere la differenza. Con addEventListener
non siamo avvolti in una onclick
funzione. Il nostro gestore riceve event
direttamente il parametro (e quindi possiamo chiamarlo come vogliamo). Inoltre il nostro return false
è al "livello più alto" qui e non dobbiamo preoccuparci di aggiungere un'istruzione di ritorno extra come con onclick
.
Quindi sembra che dovrebbe funzionare. Cliccando sul link otteniamo l'avviso. Ignora l'avviso e la pagina naviga / si aggiorna. cioè l'evento NON è stato annullato restituendo false.
Se cerchiamo le specifiche (vedi risorse in fondo), vediamo che la nostra funzione callback / handler per addEventListener non supporta un tipo restituito. Possiamo restituire quello che vogliamo, ma poiché non fa parte dell'API / interfaccia del browser, non ha alcun effetto.
Soluzione: utilizzando event.preventDefault()
invece di return false;
...
function eventHandler (ev) {
ev.preventDefault();
alert('eventHandler ran');
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();
strumenti di sviluppo del browser ...
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener);
dà ...
function eventHandler (ev) {
ev.preventDefault();
alert('eventHandler ran');
}
...come previsto.
Riprovare:
- Fare clic sul collegamento.
- Ricevi l'avviso.
- Ignora avviso.
- Non avviene alcuna navigazione o aggiornamento della pagina ... che è ciò che vogliamo.
Quindi con l' addEventListener
uso event.preventDefault()
come la restituzione di false non fa nulla.
Risorse
La specifica html5 ( https://www.w3.org/TR/html5/webappapis.html#events ) confonde le cose perché usano entrambi onclick
e addEventListener
nei loro esempi e dicono quanto segue:
L'algoritmo di elaborazione del gestore eventi per un gestore eventi H e un oggetto Evento E è il seguente:
...
- Elabora il valore restituito come segue:
...
Se il valore restituito è un valore falso booleano Web IDL, annullare l'evento.
Quindi sembra implicare che return false
annulli l'evento per entrambi addEventListener
e onclick
.
Ma, se guardi la loro definizione collegata di event-handler
te, vedi:
Un gestore di eventi ha un nome, che inizia sempre con "on" ed è seguito dal nome dell'evento a cui è destinato.
...
I gestori di eventi vengono esposti in uno dei due modi.
Il primo modo, comune a tutti i gestori di eventi, è come attributo IDL del gestore di eventi.
Il secondo modo è come attributo di contenuto del gestore di eventi. I gestori di eventi sugli elementi HTML e alcuni dei gestori di eventi sugli oggetti Window vengono esposti in questo modo.
https://www.w3.org/TR/html5/webappapis.html#event-handler
Quindi sembra che l' return false
annullamento dell'evento si applichi davvero solo ai gestori di eventi onclick
(o in generale on*
) e non ai gestori di eventi registrati tramite i addEventListener
quali ha un'API diversa.
Poiché l' addEventListener
API non è coperta dalle specifiche html5 (solo i on*
gestori di eventi) ... sarebbe meno confuso se si attenessero ai on*
gestori di eventi di stile nei loro esempi.