AddEventListener'daki useCapture parametresi anlaşılamıyor


290

Https://developer.mozilla.org/en/DOM/element.addEventListener adresindeki makaleyi okudum, ancak useCaptureözelliği anlayamıyorum . Tanım var:

True olursa, useCapture, kullanıcının yakalamayı başlatmak istediğini belirtir. Yakalamayı başlattıktan sonra, belirtilen türde tüm olaylar DOM ağacının altındaki herhangi bir EventTarget'a gönderilmeden önce kayıtlı dinleyiciye gönderilir. Ağaçta yukarı doğru hareket eden olaylar, yakalamayı kullanmak için belirlenmiş bir dinleyiciyi tetiklemez.

Bu kod üst olayı çocuk önce tetikler, bu yüzden onun davranışını anlayamıyorum.Document nesnesi usecapture true ve child div usecapture yanlış ayarlanmış ve belge usecapture izlenir.Bu yüzden neden belge özelliği alt öğe tercih edilir.

function load() {
  document.addEventListener("click", function() {
    alert("parent event");
  }, true);

  document.getElementById("div1").addEventListener("click", function() {
    alert("child event");
  }, false);
}
<body onload="load()">
  <div id="div1">click me</div>
</body>

Yanıtlar:


350

Olaylar iki durumda etkinleştirilebilir: Başlangıçta ("yakalama") ve sonunda ("kabarcık"). Olaylar, tanımlanma sırasına göre yürütülür. Diyelim ki 4 olay dinleyicisi tanımladınız:

window.addEventListener("click", function(){console.log(1)}, false);
window.addEventListener("click", function(){console.log(2)}, true);
window.addEventListener("click", function(){console.log(3)}, false);
window.addEventListener("click", function(){console.log(4)}, true);

Günlük iletileri şu sırayla görünür:

  • 2(ilk olarak, kullanılarak tanımlanır capture=true)
  • 4(kullanılarak ikinci tanımlanır capture=true)
  • 1(ile ilk tanımlı etkinlik capture=false)
  • 3(ile ikinci tanımlanmış etkinlik capture=false)

49
Yürütmenin Sipariş edilir garanti edilmez : no specification is made as to the order in which they will receive the event with regards to the other EventListeners on the EventTarget. Tüm tarayıcıları test etmedim, bu yüzden hepsini aynı şekilde uygulayabilirler. Ancak yakalama olayları, yakalamayan olaylardan önce yapılacaktır.
beatgammit

47
yürütme sırasını @tjameson edilir DOM2 spec halefi garanti, DOM3 olaylar : "uygulaması geçerli hedefin belirlenmesi gerekir aday olay dinleyicileri Bu mevcut hedef üzerinde kayıtlı olan tüm olay dinleyicileri listesi olmalıdır onların. kayıt sırası. "
Rob W

1
yani bu temelde olay siparişi ile ilgili var sanırım
slier

1
@slier, evet, aynı olay için birden çok işleyicinin yürütüldüğü sıra.
JMD

6
Afaik'ten bu yana kabul edilen cevap olduğunu bilmiyorum, çoğaltma, bitişik olay işleyicileri için yürütme sırasını dikte etmek değil, yayılma davranışı hakkında konuşma ve köpürme görüşmeleri
georaldc

272

Bu diyagramın yakalama / hedef / kabarcık aşamalarını anlamak için çok yararlı olduğunu düşünüyorum: http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

Aşağıda, bağlantıdan çıkarılan içerik.

Aşamaları

Olay, ağacın kökünden bu hedef düğüme giden bir yol izlenerek gönderilir. Daha sonra yerel olarak hedef düğüm seviyesinde veya ağaçtaki daha yüksek herhangi bir hedefin atalarından idare edilebilir. Olay dağıtımı (olay yayılımı olarak da adlandırılır) üç aşamada ve aşağıdaki sırada gerçekleşir:

  1. Yakalama aşaması: olay, hedefin atalarına ağacın kökünden hedef düğümün doğrudan üst öğesine gönderilir.
  2. Hedef aşama: olay hedef düğüme gönderilir.
  3. Köpürme aşaması: olay, hedef düğümün doğrudan üst öğesinden ağacın köküne kadar hedefin atalarına gönderilir.

DOM olay akışı kullanılarak DOM ağacına gönderilen bir olayın grafik temsili

Hedefin ataları olayın ilk gönderilmesinden önce belirlenir. Hedef düğüm gönderme sırasında kaldırılırsa veya bir hedefin atası eklenir veya kaldırılırsa, olay yayılımı her zaman hedef düğümü temel alır ve gönderilmeden önce hedefin ataları belirlenir.

Bazı olayların DOM olay akışının üç aşamasını tamamlaması gerekmeyebilir, örneğin olay yalnızca bir veya iki aşama için tanımlanabilir. Örnek olarak, bu spesifikasyonda tanımlanan olaylar her zaman yakalama ve hedef aşamalarını gerçekleştirecek, ancak bazıları kabarcıklanma aşamasını gerçekleştirmeyecektir ("kabarcıklanmayan olaylar yerine" kabarcıklanmayan olaylar ", ayrıca Event.bubbles özniteliğine bakın).


1
çok güzel bir diyagram!
Alex

1
Hedef düğümün çocukları ne olacak? Etkinliği ne zaman alırlar?
Aurimas

Ağacın kökü aslında Windowyerine, documentçünkü documentçocuğudur Window?
stackjlei

1
@Aurima'lar anlamıyorlar, mantıklı olmazdı. Hedef, olayı alması gereken en iç öğedir. Yani <body> öğesini (boş bir yer) tıklarsanız, <body> (= sayfanın tüm öğeleri) içindeki tüm öğeler açıkça click etkinliğini almamalıdır.
amik

1
Ben sadece "ne" bir "neden" dahil açıklayan tüm kaynakları diliyorum. Her zamanki gibi daha fazla googling için kapalı.
aaaaaa

80

Olayı Yakala ( useCapture = true) ve Kabarcık Etkinliği ( useCapture = false)

MDN Referansı

  • Capture Event, Bubble Event'den önce gönderilecek
  • Olay yayınlama sırası
    1. Veli Yakalama
    2. Çocuk Yakalama
    3. Hedef Yakalama ve Hedef Kabarcık
      • Kayıtlı oldukları sırayla
      • Öğe etkinliğin hedefi olduğunda, useCaptureparametre önemli değildir (Thanks @bam ve @ legend80s)
    4. Çocuk Balonu
    5. Ebeveyn Balonu
  • stopPropagation() akışı durduracak

Yakalama akışını kullanma

gösteri

Sonuç:

  1. Veli Yakalama
  2. Hedef Kabarcık 1

    (Yakalama ve Hedef Baloncuğu kaydedildikleri sırayla tetikleyeceğinden, Kabarcık etkinliği Yakalama etkinliğinden önce tetiklenir)

  3. Hedef Yakalama

  4. Hedef Kabarcık 2
  5. Ebeveyn Balonu

var parent = document.getElementById('parent'),
target = document.getElementById('target');

target.addEventListener('click', function (e) { 
console.log('Target Bubble 1');
// e.stopPropagation();
}, false);

target.addEventListener('click', function (e) { 
console.log('Target Capture');
// e.stopPropagation();
}, true);

target.addEventListener('click', function (e) { 
console.log('Target Bubble 2');
// e.stopPropagation();
}, false);

parent.addEventListener('click', function (e) { 
console.log('Parent Capture');
// e.stopPropagation();
}, true);

parent.addEventListener('click', function (e) { 
console.log('Parent Bubble');
// e.stopPropagation();
}, false);
<div id="parent">
    <button id="target" style="padding: 1em 0.8em;">
        Trigger event
    </button>
</div>


1
Örneğin bir hata var: sırayla çocuk olayları beyan ettiniz: 1. çocuk yakalama 2. çocuk balonu Önemli! Çocuk etkinliğin hedefi olacaksa, dinleyiciler aynı sırada çağrılacaktır. MDN'deki nota bakın: öğe 'useCapture' olayının hedefi olduğunda önemli değildir. ( developer.mozilla.org/tr-TR/docs/Web/API/EventTarget/… )
bam

1
Not : Olay hedefine bağlı olay dinleyicileri için, olay yakalama ve köpürme aşamaları yerine hedef aşamadadır. Events in the target phase will trigger all listeners on an element in the order they were registered, regardless of the useCapture parameter.Gönderen developer.mozilla.org/en-US/docs/Web/API/EventTarget/... . Yani "Çocuk Yakalama" ve "Çocuk Balonu" aşamaları yoktur.
legend80s

Ve bu, örnek çalıştırmanın neden "Çocuk yakalama" dan önce "Çocuk balonu 1" ürettiğini açıklar;
Gershom

18

UseCapture = true dediğinizde, yanlış olduğunda alttan üste bir kabarcık yaptığında Olaylar yakalama aşamasında yukarıdan aşağıya doğru yürütülür.


11

Her şey olay modelleri hakkında: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow Köpürme aşamasında veya yakalama aşamasında olay yakalayabilirsiniz. Senin seçimin. Http://www.quirksmode.org/js/events_order.html adresine
bir göz atın - çok faydalı bulacaksınız.


1
w3 bağlantıları google arama gibi orada bir şey anlayamıyorum kadar veya daha az yararlıdır.
Muhammed Umer

3
Evet, bu w3 bağlantısı sadece büyük bir kelime grubudur , ancak bunun tersine, quirksmode sitesine ikinci bağlantı konuyu çok iyi ve kısaca açıklar.
Stano

11

Kod örneği:

<div id="div1" style="background:#9595FF">
  Outer Div<br />
  <div id="div2" style="background:#FFFFFF">
    Inner Div
  </div>
</div>

Javascript kodu:

d1 = document.getElementById("div1");
d2 = document.getElementById("div2");

ikisi de yanlış olarak ayarlanırsa

d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},false);

Yürütür: Onclick Inner Div, uyarılar şu şekilde görüntülenir: Div 2> Div 1

Burada komut dosyası iç öğeden yürütülür: Event Bubbling (useCapture false olarak ayarlandı)

div 1 true değerine ve div 2 false değerine ayarlandı

d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},false);

Execute: Onclicking Inner Div, uyarılar şu şekilde görüntülenir: Div 1> Div 2

Burada komut dosyası atadan / dış öğeden yürütülür: Olay Yakalama (useCapture true olarak ayarlandı)

div 1, false değerine ve div 2, true değerine ayarlanır

d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},true);

Yürütür: Onclick Inner Div, uyarılar şu şekilde görüntülenir: Div 2> Div 1

Burada komut dosyası iç öğeden yürütülür: Event Bubbling (useCapture false olarak ayarlandı)

div 1 true olarak ve div 2 true olarak ayarlandı

d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},true);

Execute: Onclicking Inner Div, uyarılar şu şekilde görüntülenir: Div 1> Div 2

Burada komut dosyası ata / dış öğeden yürütülür: useCapture true olarak ayarlandığından beri Olay Yakalama


1
Bu bağlamda "daha büyük" köşeli çift ayraçlarının anlamı nedir?
2540625

9

Özet:

DOMTarif edilen spec:

https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

aşağıdaki şekilde çalışır:

documentAğacın kökünden ( ) hedef düğüme giden bir yol izlenerek bir olay gönderilir . Hedef düğüm en derin HTMLöğedir, yani event.target. Olay dağıtımı (olay yayılımı olarak da adlandırılır) üç aşamada ve aşağıdaki sırada gerçekleşir:

  1. Yakalama aşaması: olay, hedefin atalarına ağacın kökünden ( document) hedef düğümün doğrudan üst öğesine gönderilir.
  2. Hedef aşama: olay hedef düğüme gönderilir. Hedef aşama her zaman htmlolayın dağıtıldığı en derin öğedir.
  3. Köpürme aşaması: olay, hedef düğümün doğrudan üst öğesinden ağacın köküne kadar hedefin atalarına gönderilir.

Olay köpürme, olay yakalama, olay hedefi

Misal:

// bubbling handlers, third argument (useCapture) false (default)
document.getElementById('outerBubble').addEventListener('click', () => {
  console.log('outerBubble');
}, false)

document.getElementById('innerBubble').addEventListener('click', () => {
  console.log('innerBubble');
}, false)


// capturing handlers, third argument (useCapture)  true
document.getElementById('outerCapture').addEventListener('click', () => {
  console.log('outerCapture');
}, true)

document.getElementById('innerCapture').addEventListener('click', () => {
  console.log('innerCapture');
}, true)
div:hover{
  color: red;
  cursor: pointer;
}
<!-- event bubbling -->
<div id="outerBubble">
  <div id="innerBubble">click me to see Bubbling</div>
</div>


<!-- event capturing -->
<div id="outerCapture">
  <div id="innerCapture">click me to see Capturing</div>
</div>

Yukarıdaki örnek, olay köpürme ve olay yakalama arasındaki farkı gerçekten göstermektedir. İle olay dinleyicileri eklenirken, addEventListeneruseCapture adlı üçüncü bir öğe vardır. Bu booleanayarlı trueyerine olay köpüren yakalayan kullanımı olayına olay dinleyicisi verir.

Örneğimizde, useCapture argümanını ayarladığımızda, falseolayın köpürmesinin gerçekleştiğini görüyoruz. İlk olarak hedef fazdaki olay tetiklenir (logBubble günlükleri) ve daha sonra olay köpürme yoluyla üst öğedeki olay tetiklenir (dışBubble günlükleri).

UseCapture argümanını ayarladığımızda, trueönce dıştaki olayın <div>tetiklendiğini görürüz . Bunun nedeni, olayın artık köpürme aşamasında değil, yakalama aşamasında tetiklenmesidir.


7

Olay seyahatinin üç aşaması göz önüne alındığında :

  1. Yakalama aşaması : Olay hedef düğümün direkt ebeveyne ağacın kökünden hedefin atalarına gönderilir.
  2. Hedef aşaması : Olay hedef düğüme gönderilir.
  3. Köpürme aşaması : Olay ağacın köküne hedef düğümün direkt ebeveynden hedefin atalarına gönderilir.

useCaptureetkinlik seyahatinin hangi aşamalarda olacağını belirtir :

Eğer true, useCapture kullanıcı yalnızca, yani bu olay dinleyici hedef ve köpürme aşamalarına sırasında tetiklenmeyecektir yakalama aşaması için olay dinleyicisi eklemek istediğini belirtir. Eğer false, olay dinleyici yalnızca hedef ve köpürme aşamalarında tetiklenecek

Kaynak en iyi ikinci cevapla aynıdır: https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases


2

Tanımlama sırası, yalnızca öğeler aynı düzeydeyse önemlidir. Kodunuzdaki tanım sırasını tersine çevirirseniz aynı sonuçları alırsınız.

Ancak, iki olay işleyicisindeki useCapture ayarını tersine çevirirseniz, alt olay işleyicisi üst öğeden önce yanıt verir. Bunun nedeni, alt olay işleyicisinin artık, ana olay işleyicinin tetikleneceği köpürme aşamasından önceki yakalama aşamasında tetiklenmesidir.

Tanım sırasından bağımsız olarak useCapture öğesini her iki olay işleyici için true olarak ayarlarsanız, ana olay işleyicisi ilk olarak tetiklenir, çünkü yakalama aşamasında çocuktan önce gelir.

Bunun tersine, her iki olay işleyicisi için useCapture öğesini false değerine ayarlarsanız - yine tanım sırasına bakılmaksızın - köpürme aşamasında üst öğeden önce geldiği için ilk olarak alt olay işleyicisi tetiklenir.

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.