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. onclickattributo 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'
getEventListenersAPI 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' clickevento 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-hookche 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=functionNamesia 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 functionNameviene 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 onclickfunzione non restituirebbe quel valore falso ... che è richiesto per 'annullare' l'evento.
Per risolvere questo problema, possiamo impostare onclicksu be return myHandlerFunc();che garantisce che onclickrestituisca il valore restituito (false) da myHandlerFunc.
Potresti anche rimuovere return false;da myHandlerFunce modificare onclickin essere, myHandlerFunc(); return false;ma questo ha meno senso poiché probabilmente vorrai mantenere la logica insieme nella tua funzione gestore.
Nota quando si imposta onclickcon javascript , quando si sta impostando onclickdirettamente in html piuttosto che con javascript (come i miei esempi), il onclickvalore dell'attributo è di tipo stringa e tutto funziona. Se stai impostando onclickusando javascript, devi prestare attenzione al tipo. Se dici element.setAttribute('onclick', myHandlerFunc()) myHandlerFuncche 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 eventparametro al momento dell'evento, dovresti notare che si chiama "evento". È possibile accedervi all'interno del gestore utilizzando il nome event(disponibile tramite l' onclickambito della funzione padre ). Oppure puoi costruire il tuo gestore da prendere eventcome 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 addEventListenernon siamo avvolti in una onclickfunzione. Il nostro gestore riceve eventdirettamente 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' addEventListeneruso 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 onclicke addEventListenernei 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 falseannulli l'evento per entrambi addEventListenere onclick.
Ma, se guardi la loro definizione collegata di event-handlerte, 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 falseannullamento dell'evento si applichi davvero solo ai gestori di eventi onclick(o in generale on*) e non ai gestori di eventi registrati tramite i addEventListenerquali ha un'API diversa.
Poiché l' addEventListenerAPI 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.