Apa itu acara yang menggelegak dan menangkap?

Jawaban:

1441

Gelembung dan penangkapan peristiwa adalah dua cara propagasi acara di API HTML DOM, ketika suatu peristiwa terjadi dalam suatu elemen di dalam elemen lain, dan kedua elemen telah mendaftarkan pegangan untuk peristiwa itu. Mode propagasi acara menentukan urutan elemen yang menerima acara .

Dengan menggelegak, acara pertama-tama ditangkap dan ditangani oleh elemen paling dalam dan kemudian disebarkan ke elemen luar.

Dengan menangkap, acara pertama-tama ditangkap oleh elemen terluar dan disebarkan ke elemen dalam.

Menangkap juga disebut "trickling", yang membantu mengingat urutan propagasi:

menetes ke bawah, menggembung ke atas

Kembali di masa lalu, Netscape menganjurkan penangkapan acara, sementara Microsoft mempromosikan acara bubbling. Keduanya adalah bagian dari Acara Model Objek Dokumen W3C (2000).

IE <9 hanya menggunakan event bubbling , sedangkan IE9 + dan semua browser utama mendukung keduanya. Di sisi lain, kinerja peristiwa menggelegak mungkin sedikit lebih rendah untuk DOM kompleks.

Kita dapat menggunakan addEventListener(type, listener, useCapture)untuk mendaftarkan pengendali acara baik dalam mode menggelegak (default) atau menangkap. Untuk menggunakan model penangkapan, lewati argumen ketiga sebagai true.

Contoh

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

Dalam struktur di atas, asumsikan bahwa peristiwa klik terjadi di lielemen.

Dalam menangkap model, acara akan ditangani oleh yang divpertama (klik penangan acara di divapi akan pertama), kemudian di ul, kemudian pada yang terakhir di elemen target,li ,.

Dalam model bubbling, kebalikannya akan terjadi: acara akan pertama-tama ditangani oleh li, kemudian oleh ul, dan akhirnya oleh divelemen.

Untuk informasi lebih lanjut, lihat

Dalam contoh di bawah ini, jika Anda mengklik salah satu elemen yang disorot, Anda dapat melihat bahwa fase penangkapan dari aliran propagasi acara terjadi terlebih dahulu, diikuti oleh fase menggelegak.

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>

Contoh lain di JSFiddle .

Arun P Johny
sumber
41
useCapturesekarang didukung di IE> = 9. sumber
beatgammit
7
Saya tahu sudah terlambat untuk berkomentar tapi artikel bagus yang saya temukan di sini catcode.com/domcontent/events/capture.html
Hanya kode
3
Apakah triclklingsama dengan capturing? Pembicaraan Crockford dalam pembicaraan Trickling v. Bubblingvideo ini - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB sekitar 1 hr 5 minutes.
Kevin Meredith
1
@KevinMeredith Hal yang sama. "Trickling" hanya membuatnya lebih mudah mengingat apa yang dilakukan kedua model (trickle down , bubble up ).
seekor kucing
7
Jawaban di atas benar sehubungan dengan urutan dalam penjelasan terperinci, tetapi membuat Anda berpikir bahwa tetesan muncul di urutan kedua dengan "gelembung naik, mengalir turun". Acara selalu melewati fase penangkapan sebelum fase gelembung. Urutan yang benar adalah trickle down=> onElement=>bubble up
runspired
513

Deskripsi:

quirksmode.org memiliki deskripsi yang bagus tentang ini. Singkatnya (disalin dari quirksmode):

Pengambilan acara

Saat Anda menggunakan penangkapan acara

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

pengendali event elemen1 pertama yang terbakar, pengendali event elemen2 terakhir.

Gelembung acara

Saat Anda menggunakan acara bubbling

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

pengendali event elemen2 pertama yang dipecat, pengendali event elemen1 terakhir.


Apa yang harus digunakan?

Itu tergantung pada apa yang ingin Anda lakukan. Tidak ada yang lebih baik. Perbedaannya adalah urutan pelaksanaan penangan acara. Sebagian besar waktu akan baik-baik saja untuk memecat event handler dalam fase menggelegak tetapi juga bisa diperlukan untuk memecat mereka lebih awal.

Felix Kling
sumber
Tidak keduanya terjadi, pertama menangkap dan kemudian menggelegak, juga apa itu acara pengiriman?
Suraj Jain
contoh grafis ada di sini: javascript.info/bubbling-and-capturing
Komunitas Ans
71

Jika ada dua elemen elemen 1 dan elemen 2. Elemen 2 ada di dalam elemen 1 dan kami lampirkan event handler dengan kedua elemen tersebut, misalkan onClick. Sekarang ketika kita klik pada elemen 2 maka eventHandler untuk kedua elemen akan dieksekusi. Sekarang di sini pertanyaannya adalah urutan acara yang akan dieksekusi. Jika acara yang dilampirkan dengan elemen 1 dieksekusi terlebih dahulu itu disebut peristiwa menangkap dan jika acara terlampir dengan elemen 2 dieksekusi pertama ini disebut peristiwa bubbling. Sesuai W3C acara akan dimulai pada fase menangkap hingga mencapai target kembali ke elemen dan kemudian mulai menggelegak

Status menangkap dan menggelegak dikenal oleh parameter useCapture dari metode addEventListener

eventTarget.addEventListener (tipe, pendengar, [, useCapture]);

Secara Default useCapture salah. Itu berarti berada dalam fase menggelegak.

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>

Silakan coba dengan mengubah benar dan salah.

dinesh_malhotra
sumber
2
@ masterxilo: tidak perlu untuk Fiddle, StackOverflow sekarang mendukung kode inline (stack snippets) .
Dan Dascalescu
Mengenai the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubbling. Saya hanya menemukan addEventListener memiliki parameter useCaptureyang dapat disetel ke true atau false; dan dalam HTML 4.0, pendengar acara ditetapkan sebagai atribut elemen dan useCapture defaults to false. Bisakah Anda menautkan ke spesifikasi yang mengkonfirmasi apa yang Anda tulis?
surfmuggle
25

Saya menemukan tutorial ini di javascript.info sangat jelas dalam menjelaskan topik ini. Dan ringkasan 3 poinnya di akhir benar-benar berbicara dengan poin-poin penting. Saya kutip di sini:

  1. Peristiwa pertama ditangkap hingga target terdalam, lalu meluap. Di IE <9 mereka hanya menggelembung.
  2. Semua penangan bekerja di atas panggung menggelegak kecuali addEventListenerdengan argumen terakhir true, yang merupakan satu-satunya cara untuk menangkap peristiwa pada tahap menangkap.
  3. Bubbling / capturing dapat dihentikan oleh event.cancelBubble=true(IE) atau event.stopPropagation() untuk browser lain.
gm2008
sumber
7

Ada juga Event.eventPhaseproperti yang dapat memberi tahu Anda apakah acara tersebut sesuai target atau berasal dari tempat lain.

Perhatikan bahwa kompatibilitas browser belum ditentukan. Saya mengujinya di Chrome (66.0.3359.181) dan Firefox (59.0.3) dan didukung di sana.

Memperluas potongan yang sudah bagus dari jawaban yang diterima , ini adalah output menggunakan eventPhaseproperti

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>

Adelin
sumber
5

Bual

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

Menangkap

  Event propagate from body(root) element to eventTriggered Element is **CAPTURING**.
Kondal
sumber