Come passare l'evento come argomento a un gestore di eventi inline in JavaScript?


103
// this e works
document.getElementById("p").oncontextmenu = function(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
};

// this e is undefined
function doSomething(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}
<p id="p" onclick="doSomething(e)">
    <a href="#">foo</a>
    <span>bar</span>
</p>

Sono state poste alcune domande simili.

Ma nel mio codice, sto cercando di ottenere elementi figlio su cui è stato fatto clic, come aospan .

Allora qual è il modo corretto di passare eventcome argomento al gestore di eventi o come ottenere un evento all'interno del gestore senza passare un argomento?

modificare

Sono a conoscenza addEventListenere jQuery, per favore, fornisci una soluzione per passare da un evento all'altro inline.



5
C'è una buona ragione per utilizzare gestori di eventi inline piuttosto che passare a addEventListener? en.wikipedia.org/wiki/Unobtrusive_JavaScript
Xotic750

2
@ Xotic750 Per me sì, non c'è bisogno di preoccuparsi di ricollegarli manualmente ogni volta che si carica o si ricarica dinamicamente html tramite ajax, ad esempio.
Wadih M.

Risposte:


166

per passare l' eventoggetto:

<p id="p" onclick="doSomething(event)">

per ottenere il bambino cliccato element(dovrebbe essere usato con il eventparametro:

function doSomething(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}

per passare lo elementstesso (DOMElement):

<p id="p" onclick="doThing(this)">

guarda un esempio dal vivo su jsFiddle


11
(E per chiunque si chieda: Sì, funziona su Chrome, Firefox, ecc., Anche se alcuni [Firefox, ad esempio] non hanno un eventoggetto globale . È perché il contesto in cui viene chiamato il gestore DOM0 ha un eventoggetto , anche se [su alcuni browser] non è globale.)
TJ Crowder

thissi riferisce a p, ma sto cercando di ottenere aospan
user1643156

3
Passare un "evento" è l'unico modo che conosco, a condizione che sia supportato. Analizzare "questo" è inutile in questa situazione
Xotic750

5
@ user1643156 È molto importante. il parametro deve essere denominato esattamente come "evento"
The-null-Pointer -

1
La risposta di Wadih M. è decisamente migliore di questa. Questo è fuorviante (come altri simili), facendo credere alle persone che il parametro "(evento)" dovrebbe essere inserito nella chiamata della funzione, quando, in realtà, JavaScript ha il parametro "evento" già e prontamente disponibile all'interno della funzione chiamata, quindi non c'è bisogno di dichiararlo (mi ci sono voluti giorni per rendermi conto che non faceva differenza cambiare il nome della variabile, perché non veniva realmente passato). Inoltre, la spiegazione fornita qui elimina ogni dubbio sul motivo per cui JS funziona in questo modo (forse non dovrebbe, ma non spetta a me giudicare ...)
Cyberknight

15

Poiché gli eventi inline vengono eseguiti come funzioni, puoi semplicemente utilizzare gli argomenti .

<p id="p" onclick="doSomething.apply(this, arguments)">

e

function doSomething(e) {
  if (!e) e = window.event;
  // 'e' is the event.
  // 'this' is the P element
}

L '"evento" menzionato nella risposta accettata è in realtà il nome dell'argomento passato alla funzione. Non ha niente a che fare con l'evento globale.


Bel consiglio. Quando le persone inizieranno ad adottare componenti web call()e apply()si dimostreranno essenziali per emulare le capacità di data binding disponibili nei framework js tradizionali. Un trucco in più è fare qualcosa di simile Object.assign(this.querySelector('my-btn'), this)all'interno di un componente web e voilà, associazione dati. È possibile accedere a qualsiasi metodo della classe del componente Web padre dagli eventi in linea onclick="toggleBtnActive.call(this, true)".
Adrian Moisa

8

Non è necessario passare this, c'è già l' eventoggetto passato automaticamente per impostazione predefinita, che contiene event.targetl'oggetto da cui proviene. Puoi alleggerire la tua sintassi:

Questo:

<p onclick="doSomething()">

Funzionerà con questo:

function doSomething(){
  console.log(event);
  console.log(event.target);
}

Non è necessario creare un'istanza eventdell'oggetto, è già lì. Provalo. Eevent.target conterrà l'intero oggetto chiamandolo, a cui prima facevi riferimento come "questo".

Ora, se attivi dinamicamente doSomething () da qualche parte nel tuo codice, noterai che eventnon è definito. Questo perché non è stato attivato da un evento di clic. Quindi, se vuoi ancora attivare artificialmente l'evento, usa semplicemente dispatchEvent:

document.getElementById('element').dispatchEvent(new CustomEvent("click", {'bubbles': true}));

Poi doSomething()vedremo evente event.targetcome al solito!

Non è necessario passare thisovunque e puoi mantenere le firme delle funzioni libere dalle informazioni di cablaggio e semplificare le cose.


Almeno su IE11, questo non è vero, non ci sono argomenti predefiniti.
cskwg

1
@cskwg Funziona anche per IE11. Funziona su tutti i principali browser poiché è necessario per la compatibilità con le versioni precedenti. Come ho accennato nella risposta, solo se la funzione javascript viene attivata da un evento, che è l'unico scenario in cui esiste un evento, ci sarà un oggetto già chiamato "evento" a cui puoi accedere prontamente all'interno della tua funzione senza doverlo fare passare cavi aggiuntivi al prototipo della funzione. Ho appena fatto un test sulla mia macchina con IE11 per un evento onclick e la variabile "event" conteneva un "oggetto PointerEvent".
Wadih M.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.