Olay köpürme ve yakalama nedir?


Yanıtlar:


1439

Olay köpürme ve yakalama, başka bir öğenin içindeki bir öğede bir olay meydana geldiğinde ve her iki öğe de o olay için bir tanıtıcı kaydettiğinde, HTML DOM API'sında olay yaymanın iki yoludur. Olay yayma modu , öğelerin olayı hangi sırayla alacağını belirler .

Köpürme ile, olay önce en içteki eleman tarafından yakalanır ve ele alınır ve daha sonra dış elemanlara yayılır.

Yakalama ile, olay ilk olarak en dıştaki eleman tarafından yakalanır ve iç elemanlara yayılır.

Yakalama, yayılma sırasını hatırlamaya yardımcı olan "damlama" olarak da adlandırılır:

damlatmak, havaya uçurmak

Eski günlerde, Netscape olay yakalamayı savunurken, Microsoft olay kabarcıklanmasını teşvik etti. Her ikisi de W3C Belge Nesne Modeli Olayları standardının (2000) bir parçasıdır .

IE <9 yalnızca olay köpürme kullanır , IE9 + ve tüm büyük tarayıcılar her ikisini de destekler. Öte yandan, olay köpürme performansı karmaşık DOM'lar için biraz daha düşük olabilir .

addEventListener(type, listener, useCapture)Olay işleyicilerini köpürme (varsayılan) veya yakalama modunda kaydetmek için kullanabiliriz . Yakalama modelini kullanmak için üçüncü argümanı olarak iletin true.

Misal

<div>
    <ul>
        <li></li>
    </ul>
</div>

Yukarıdaki yapıda, liöğede bir tıklama etkinliğinin oluştuğunu varsayın .

Yakalama modelinde, olay divilk (önce tetiklenecek olan tıklama işleyicileri div), daha ulsonra hedef öğede, son olarak, tarafından işlenecektir li.

Köpürme modelinde bunun tersi gerçekleşir: olay ilk önce li, sonra ul, ve sonunda diveleman tarafından ele alınacaktır .

Daha fazla bilgi için, bkz

Aşağıdaki örnekte, vurgulanan öğelerin herhangi birine tıklarsanız, olay yayılma akışının yakalama aşamasının önce köpürme aşamasının gerçekleştiğini görebilirsiniz.

var logElement = document.getElementById('log');

function log(msg) {
    logElement.innerHTML += ('<p>' + msg + '</p>');
}

function capture() {
    log('capture: ' + this.firstChild.nodeValue.trim());
}

function bubble() {
    log('bubble: ' + this.firstChild.nodeValue.trim());
}

function clearOutput() {
    logElement.innerHTML = "";
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click', capture, true);
    divs[i].addEventListener('click', bubble, false);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);
p {
    line-height: 0;
}

div {
    display:inline-block;
    padding: 5px;

    background: #fff;
    border: 1px solid #aaa;
    cursor: pointer;
}

div:hover {
    border: 1px solid #faa;
    background: #fdd;
}
<div>1
    <div>2
        <div>3
            <div>4
                <div>5</div>
            </div>
        </div>
    </div>
</div>
<button id="clear">clear output</button>
<section id="log"></section>

JSFiddle'da başka bir örnek .


41
useCaptureartık IE'de destekleniyor> = 9. kaynak
beatgammit

7
Ben yorum koymak için çok geç biliyorum ama güzel makale burada bulundu catcode.com/domcontent/events/capture.html
Sadece kod

3
İle triclklingaynı mı capturing? Hakkında Crockford görüşmeler Trickling v. Bubblingbu videonun konuşma - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB etrafında 1 hr 5 minutes.
Kevin Meredith

1
@KevinMeredith Aynı şey. "Damlatmalı" sadece daha kolay iki model (damlama ne hatırlamak yapar aşağı , kabarcık yukarı ).
bir kedi

7
Yukarıdaki cevap, ayrıntılı açıklamadaki sıraya göre doğrudur, ancak size "kabarcık yukarı, aşağı damlama" ile damlamanın ikinci olduğunu düşünmenizi sağlar. Olaylar her zaman kabarcık aşamasından önce yakalama aşamasından geçer. Doğru sipariş trickle down=> onElement=>bubble up
runspired

513

Açıklama:

quirksmode.org bunun güzel bir açıklamasına sahiptir. Özetle (quirksmode'dan kopyalandı):

Etkinlik yakalama

Etkinlik yakalamayı kullandığınızda

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

ilk olarak element1 olay işleyicisi tetiklenir, son olarak element2 olay işleyicisi tetiklenir.

Olay köpürme

Olay köpürme kullandığınızda

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

ilk olarak element2 olay işleyicisi tetiklenir, son olarak element1 olay işleyicisi tetiklenir.


Ne kullanılır?

Bu ne yapmak istediğinize bağlıdır. Daha iyisi yok. Fark, olay işleyicilerin yürütme sırasıdır. Çoğu zaman olay işleyicilerini köpürme aşamasında ateşlemek iyi olacaktır, ancak daha önce ateşlemek de gerekebilir.


Her ikisi de olmaz, önce yakalama sonra köpürme, ayrıca sevk olayı nedir?
Suraj Jain


71

Eğer eleman 1 ve eleman 2'de iki eleman varsa, eleman 2 eleman 1'in içindedir ve her iki elemanın da onClick diyelim bir olay işleyicisi ekleriz. Şimdi eleman 2'ye tıkladığımızda her iki eleman için eventHandler çalıştırılacaktır. Şimdi soru, olayın hangi sırada yürütüleceği sorusudur. Eleman 1 ile iliştirilen olay ilk önce yürütülürse, olaya olay yakalama denir ve 2 nolu eleman ile iliştirilen olay ilk olarak yürütülürse buna olay köpürme denir. W3C'ye göre olay, hedefe ulaşana kadar yakalama aşamasında başlayacak ve daha sonra köpürmeye başlayacaktır.

Yakalama ve köpürme durumları, addEventListener yönteminin useCapture parametresi tarafından bilinir.

eventTarget.addEventListener (tip, dinleyici, [useCapture]);

Varsayılan olarak useCapture yanlıştır. Bu köpürme aşamasında olduğu anlamına gelir.

var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");

div1.addEventListener("click", function (event) {
  alert("you clicked on div 1");
}, true);

div2.addEventListener("click", function (event) {
  alert("you clicked on div 2");
}, false);
#div1{
  background-color:red;
  padding: 24px;
}

#div2{
  background-color:green;
}
<div id="div1">
  div 1
  <div id="div2">
    div 2
  </div>
</div>

Lütfen doğru ve yanlış değiştirmeyi deneyin.


2
@masterxilo: Fiddle'a gerek yok, StackOverflow artık satır içi kodu (yığın snippet'lerini) destekliyor .
Dan Dascalescu

İlgili the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubbling. Ben sadece addEventListeneruseCapture true veya false olarak ayarlanabilen bir parametreye sahip bulundu ; ve HTML 4.0'da, olay dinleyicileri bir öğesinin özelliklerine olarak belirtilmiş ve useCapture defaults to false. Ne yazdığınızı doğrulayan bir spesifikasyona bağlanabilir misiniz?
22'de sörf

25

Bu konuyu açıklarken çok net olması için javascript.info bu öğretici buldum . Ve sonunda 3 puanlık özeti gerçekten önemli noktalardan bahsediyor. Burada alıntı yapıyorum:

  1. Olaylar önce en derin hedefe kadar yakalanır, sonra kabarır. IE <9 da sadece kabarcıklar.
  2. Tüm işleyiciler , olayı yakalama sahnesinde yakalamanın tek yolu olan addEventListenerson argümanla köpüren sahne istisnaları üzerinde çalışır true.
  3. Köpürme / yakalama event.cancelBubble=true(IE) veya event.stopPropagation() diğer tarayıcılar tarafından durdurulabilir .

7

Ayrıca Event.eventPhase, etkinliğin hedefte olup olmadığını veya başka bir yerden gelip gelmediğini size söyleyebilecek bir özellik de vardır .

Tarayıcı uyumluluğunun henüz belirlenmediğini unutmayın. Chrome (66.0.3359.181) ve Firefox (59.0.3) üzerinde test ettim ve orada destekleniyor.

Kabul edilen yanıttan zaten büyük snippet'e genişleyen , bu eventPhaseözelliği kullanan çıktıdır

var logElement = document.getElementById('log');

function log(msg) {
  if (logElement.innerHTML == "<p>No logs</p>")
    logElement.innerHTML = "";
  logElement.innerHTML += ('<p>' + msg + '</p>');
}

function humanizeEvent(eventPhase){
  switch(eventPhase){
    case 1: //Event.CAPTURING_PHASE
      return "Event is being propagated through the target's ancestor objects";
    case 2: //Event.AT_TARGET
      return "The event has arrived at the event's target";
    case 3: //Event.BUBBLING_PHASE
      return "The event is propagating back up through the target's ancestors in reverse order";
  }
}
function capture(e) {
  log('capture: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

function bubble(e) {
  log('bubble: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', capture, true);
  divs[i].addEventListener('click', bubble, false);
}
p {
  line-height: 0;
}

div {
  display:inline-block;
  padding: 5px;

  background: #fff;
  border: 1px solid #aaa;
  cursor: pointer;
}

div:hover {
  border: 1px solid #faa;
  background: #fdd;
}
<div>1
  <div>2
    <div>3
      <div>4
        <div>5</div>
      </div>
    </div>
  </div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>


5

köpüren

  Event propagate to the upto root element is **BUBBLING**.

Yakalama

  Event propagate from body(root) element to eventTriggered Element is **CAPTURING**.
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.