Wie übergebe ich ein Ereignis als Argument an einen Inline-Ereignishandler in JavaScript?

100
// 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>

Es wurden einige ähnliche Fragen gestellt.

Aber in meinem Code versuche ich, untergeordnete Elemente zu erhalten, auf die geklickt wurde, wie aoderspan .

Was ist also der richtige Weg, um eventein Argument an den Ereignishandler zu übergeben, oder wie kann ein Ereignis in den Handler übernommen werden, ohne ein Argument zu übergeben?

bearbeiten

Ich bin mir bewusst addEventListenerund jQuerybitte geben Sie eine Lösung für die Weitergabe von Event an inlineEvent Hander.

user1643156
quelle
5
Gibt es einen guten Grund für die Verwendung von Inline-Ereignishandlern, anstatt zu addEventListener zu wechseln? en.wikipedia.org/wiki/Unobtrusive_JavaScript
Xotic750
1
@ Xotic750 Ja, ich muss mich nicht darum kümmern, sie jedes Mal manuell neu zu binden, wenn ich beispielsweise HTML dynamisch über Ajax lade oder neu lade.
Wadih M.

Antworten:

161

um das eventObjekt zu übergeben:

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

um das angeklickte Kind zu erhalten element(sollte mit folgenden eventParametern verwendet werden:

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

sich elementselbst übergeben (DOMElement):

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

siehe Live-Beispiel auf jsFiddle

Akram Berkawy
quelle
11
(Und für alle, die sich fragen: Ja, dies funktioniert unter Chrome, Firefox usw., obwohl einige [z. B. Firefox] kein globales eventObjekt haben. Dies liegt daran, dass der Kontext, in dem der DOM0-Handler aufgerufen wird, ein eventObjekt enthält , auch wenn [in einigen Browsern] es nicht global ist.)
TJ Crowder
thisbezieht sich auf p, aber ich versuche zu bekommen aoderspan
user1643156
2
Das Bestehen von "Ereignis" ist der einzige Weg, den ich kenne, vorausgesetzt, es wird unterstützt. Das Parsen von "Dies" ist in dieser Situation nicht von Nutzen
Xotic750
5
@ user1643156 Das ist sehr wichtig. Der Parameter muss genau als "Ereignis" benannt werden
The-null-Pointer -
1
Die Antwort von Wadih M. ist viel besser als diese. Dieser ist irreführend (wie andere ähnliche) und lässt die Leute glauben, dass der Parameter "(event)" in den Funktionsaufruf eingefügt werden sollte, wenn JavaScript den Parameter "event" bereits in der aufgerufenen Funktion bereits verfügbar hat. Es ist also nicht erforderlich, es zu deklarieren (es dauerte Tage, bis mir klar wurde, dass es keinen Unterschied machte, den Variablennamen zu ändern, da er nicht wirklich übergeben wurde). Auch die dort gegebene Erklärung lässt Zweifel daran aufkommen, warum JS so funktioniert (vielleicht sollte es nicht, aber ich muss das nicht beurteilen ...)
Cyberknight
15

Da Inline-Ereignisse als Funktionen ausgeführt werden, können Sie einfach Argumente verwenden .

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

und

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

Das 'Ereignis', das in der akzeptierten Antwort erwähnt wird, ist tatsächlich der Name des an die Funktion übergebenen Arguments. Es hat nichts mit dem globalen Ereignis zu tun.

Semra
quelle
Guter Tipp. Wenn Benutzer mit der Einführung von Webkomponenten beginnen call()und apply()sich als wesentlich für die Emulation von Datenbindungsfunktionen erweisen, die in den gängigen JS-Frameworks verfügbar sind. Ein zusätzlicher Trick besteht darin, etwas Ähnliches wie Object.assign(this.querySelector('my-btn'), this)in einer Webkomponente und voila, Datenbindung, zu tun . Sie können über die Inline-Ereignisse auf jede Methode der übergeordneten Webkomponentenklasse zugreifen onclick="toggleBtnActive.call(this, true)".
Adrian Moisa
8

Sie müssen nicht übergeben this, es gibt bereits das eventObjekt, das standardmäßig automatisch übergeben wird und das event.targetdas Objekt enthält , von dem es stammt. Sie können Ihre Syntax vereinfachen:

Dies:

<p onclick="doSomething()">

Wird damit funktionieren:

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

Sie müssen das eventObjekt nicht instanziieren , es ist bereits vorhanden. Versuch es. Und event.targetenthält das gesamte Objekt, das es aufruft und das Sie zuvor als "dies" bezeichnet haben.

Wenn Sie nun dynamisch doSomething () von irgendwo in Ihrem Code auslösen, werden Sie feststellen, dass dies nicht eventdefiniert ist. Dies liegt daran, dass es nicht durch ein Ereignis des Klickens ausgelöst wurde. Wenn Sie das Ereignis dennoch künstlich auslösen möchten, verwenden Sie einfach dispatchEvent:

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

Dann doSomething()sehen eventund event.targetwie gewohnt!

Sie müssen nicht thisüberall vorbeikommen , und Sie können Ihre Funktionssignaturen frei von Verdrahtungsinformationen halten und die Dinge vereinfachen.

Wadih M.
quelle
Zumindest auf IE11 ist dies nicht wahr. Es gibt keine Standardargumente.
cskwg
1
@cskwg Es funktioniert auch für IE11. Es funktioniert in allen gängigen Browsern, da dies für die Abwärtskompatibilität erforderlich ist. Wie ich in der Antwort erwähnt habe, gibt es nur dann ein Objekt, das als "Ereignis" bezeichnet wird, auf das Sie innerhalb Ihrer Funktion problemlos zugreifen können, ohne dass dies erforderlich ist, wenn die Javascript-Funktion von einem Ereignis ausgelöst wird. Dies ist das einzige Szenario, in dem ein Ereignis vorhanden ist Übergeben Sie zusätzliche Verkabelung an Ihren Funktionsprototyp. Ich habe gerade einen Test auf meinem Computer mit IE11 für ein Onclick-Ereignis durchgeführt, und die Variable 'event' enthielt ein "PointerEvent-Objekt".
Wadih M.