JavaScript'te bir satır içi olay işleyicisine bağımsız değişken olarak olay nasıl iletilir?


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

Bazı benzer sorular soruldu.

Ama kodumda, aveya gibi tıklanan alt öğeleri almaya çalışıyorumspan .

Öyleyse eventolay işleyicisine bir argüman olarak iletmenin doğru yolu nedir veya bir argüman iletmeden olay işleyiciye nasıl alınır?

Düzenle

Farkındayım addEventListenerve jQuerylütfen olayı inlineolay işleyiciye geçirmek için bir çözüm sağlayın .



5
AddEventListener'a geçmek yerine satır içi olay işleyicilerini kullanmanın iyi bir nedeni var mı? en.wikipedia.org/wiki/Unobtrusive_JavaScript
Xotic750

2
@ Xotic750 Benim için evet, örneğin ajax aracılığıyla html'yi dinamik olarak yüklerken veya yeniden yüklerken her seferinde bunları manuel olarak yeniden bağlamayı önemsemeye gerek yok.
Wadih M.

Yanıtlar:


173

eventnesneyi geçmek için :

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

tıklanan çocuğu almak için element(şu eventparametreyle birlikte kullanılmalıdır :

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

elementkendisini geçmek için (DOMElement):

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

jsFiddle'da canlı örneğe bakın


11
(Ve merak eden herkes için: Evet, bazı [Firefox, örneğin] global bir eventnesneye sahip olmasa bile bu Chrome, Firefox vb. Üzerinde çalışır . Bunun nedeni DOM0 işleyicisinin çağrıldığı bağlamın bir eventnesneye sahip olmasıdır , [bazı tarayıcılarda] bu global olmasa bile.)
TJ Crowder

thisifade eder p, ama almaya çalışıyorum ayaspan
user1643156

3
Destekleniyorsa, "olay" ı geçmek bildiğim tek yoldur. "Bunu" ayrıştırmanın bu durumda bir
faydası

5
@ user1643156 Bu çok önemli. parametre tam olarak "olay" olarak adlandırılmalıdır
The-null-Pointer-

1
Wadih M.'nin cevabı bundan çok daha iyi. Bu yanıltıcıdır (buna benzer diğerleri gibi), insanları "(olay)" parametresinin işlev çağrısına yerleştirilmesi gerektiğine inandırır, aslında JavaScript zaten "olay" parametresine sahipse ve çağrılan işlev içinde kolayca kullanılabilir, bu yüzden onu bildirmeye gerek yok (değişken adını değiştirmenin hiçbir fark yaratmadığını anlamam günlerimi aldı, çünkü gerçekten geçmiyordu). (... belki olmamalı, ama bu yargıç üzerimde değil) Ayrıca, verilen açıklama JS böyle çalışır neden hakkında herhangi bir şüpheniz var görevden
Cyberknight

17

Satır içi olaylar işlev olarak yürütüldüğünden, basitçe argümanlar kullanabilirsiniz .

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

ve

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

Kabul edilen cevapta bahsedilen 'olay' aslında işleve aktarılan argümanın adıdır. Küresel olay ile ilgisi yok.


İyi bahşiş. İnsanlar web bileşenlerini benimsemeye başladığında call()ve apply()ana akım js çerçevelerinde bulunan veri bağlama yeteneklerini taklit etmede önemli olduğunu kanıtlayacak. Ekstra bir numara, Object.assign(this.querySelector('my-btn'), this)bir web bileşeni ve işte veri bağlamaya benzer bir şey yapmaktır . Satır içi olaylardan üst web bileşeni sınıfının herhangi bir yöntemine erişebilirsiniz onclick="toggleBtnActive.call(this, true)".
Adrian Moisa

9

Geçmenize gerek yok this, zaten eventvarsayılan olarak otomatik olarak geçirilen nesne var , hangi event.targetnesneden geldiği var. Söz diziminizi hafifletebilirsiniz:

Bu:

<p onclick="doSomething()">

Bununla çalışacak:

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

eventNesneyi somutlaştırmanıza gerek yok , zaten oradadır. Denemek. Ve event.targetdaha önce "bu" olarak adlandırdığınız, onu çağıran tüm nesneyi içerecektir.

Şimdi doSomething () işlevini kodunuzun herhangi bir yerinden dinamik olarak tetiklerseniz, eventbunun tanımsız olduğunu fark edeceksiniz . Bunun nedeni, bir tıklama olayından tetiklenmemiş olmasıdır. Bu nedenle, olayı hala yapay olarak tetiklemek istiyorsanız, şunu kullanın dispatchEvent:

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

Sonra doSomething()görecek eventve event.targether zamanki gibi!

thisHer yere geçmenize gerek yok ve işlev imzalarınızı kablolama bilgilerinden uzak tutabilir ve işleri basitleştirebilirsiniz.


En azından IE11'de bu doğru değil, Varsayılan argüman yok.
cskwg

1
@cskwg IE11 için de çalışıyor. Geriye dönük uyumluluk için gerekli olduğundan tüm büyük tarayıcılarda çalışır. Cevapta bahsettiğim gibi, yalnızca javascript işlevi bir olayın var olduğu tek senaryo olan bir olaydan çalıştırılırsa, işlevinizin içinden kolayca erişebileceğiniz "olay" olarak adlandırılan bir nesne olacaktır. fonksiyon prototipinize fazladan kablo geçirin. Makinemde bir onclick olayı için IE11 ile bir test yaptım ve "olay" değişkeni bir "PointerEvent nesnesi" içeriyordu.
Wadih M.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.