Pertanyaan Apa acara menggelegak dan menangkap?


Apa perbedaan antara acara meluap dan menangkap? Dari keduanya, model mana yang lebih cepat dan lebih baik untuk digunakan?


826
2018-01-06 15:44


asal


Jawaban:


Acara menggelegak dan menangkap adalah dua cara propagasi acara di API DOM HTML, ketika suatu peristiwa terjadi di elemen di dalam elemen lain, dan kedua elemen telah mendaftarkan pegangan untuk peristiwa itu. Mode propagasi event menentukan dalam yang memerintahkan elemen menerima acara.

Dengan menggelegak, acara ini pertama kali ditangkap dan ditangani oleh elemen terdalam dan kemudian disebarkan ke elemen luar.

Dengan menangkap, peristiwa ini pertama kali ditangkap oleh elemen terluar dan disebarkan ke elemen batin.

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

menetes ke bawah, meluap

Di masa lalu, Netscape mengadvokasi acara, sementara Microsoft mempromosikan acara yang menggelegak. Keduanya merupakan bagian dari W3C Acara Model Objek Dokumen standar (2000).

IE <9 digunakan hanya acara yang menggelembung, sedangkan IE9 + dan semua browser utama mendukung keduanya. Di sisi lain, itu kinerja acara menggelembung mungkin sedikit lebih rendah untuk DOM kompleks.

Kami bisa menggunakan addEventListener(type, listener, useCapture) untuk mendaftarkan penangan kejadian baik dalam mode gelembung (default) atau menangkap. Untuk menggunakan model penangkapan, berikan argumen ketiga sebagai true.

Contoh

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

Dalam struktur di atas, asumsikan bahwa peristiwa klik terjadi di li elemen.

Dalam menangkap model, acara akan ditangani oleh div pertama (klik pengendali event di div akan diaktifkan pertama), lalu di ul, lalu pada elemen target terakhir, li.

Dalam model menggelegak, kebalikannya akan terjadi: acara akan ditangani pertama oleh li, lalu oleh ul, dan akhirnya oleh div elemen.

Untuk informasi lebih lanjut, lihat

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

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());
}

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>
<section id="log"></section>

Contoh lain di JSFiddle.


1146
2018-01-06 15:47



Deskripsi:

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

Pengambilan acara

Saat Anda menggunakan pengambilan acara

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

event handler dari element1 menembak pertama, pengendali event dari elemen2 menyala terakhir.

Acara menggelegak

Saat Anda menggunakan acara bergelembung

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

pengendali event dari elemen2 api pertama, pengendali event dari elemen1 api terakhir.


Apa yang harus digunakan?

Itu tergantung pada apa yang ingin Anda lakukan. Tidak ada yang lebih baik. Perbedaannya adalah urutan eksekusi penangan kejadian. Sebagian besar waktu akan baik-baik saja untuk memecat penangan event di bual fase tetapi juga dapat diperlukan untuk memecat mereka sebelumnya.


455
2018-01-06 15:46



Jika ada dua elemen elemen 1 dan elemen 2. Elemen 2 ada di dalam elemen 1 dan kami melampirkan event handler dengan kedua elemen katakan pada Klik. Sekarang ketika kita klik pada elemen 2 maka eventHandler untuk kedua elemen akan dieksekusi. Sekarang di sini pertanyaannya adalah urutan urutan mana yang akan dieksekusi. Jika event yang dilampirkan dengan elemen 1 mengeksekusi pertama itu disebut event capturing dan jika event yang dilampirkan dengan elemen 2 mengeksekusi pertama ini disebut acara menggelegak. Sesuai W3C, acara akan dimulai dalam fase penangkapan hingga mencapai target kembali ke elemen dan kemudian mulai menggelembung

Status pengambilan dan penggelembungan dikenal dengan parameter useCapture metode addEventListener

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

Dengan Default useCapture salah. Itu berarti dalam fase mendidih.

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.


63
2018-03-04 12:45



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

  1. Acara pertama ditangkap turun ke target terdalam, lalu meluap. Di   IE <9 hanya gelembung.
  2. Semua penangan bekerja pada tahap menggelembung kecuali   addEventListener dengan argumen terakhir benar, yang merupakan satu-satunya cara untuk   tangkap acara pada tahap penangkapan.
  3. Bubbling / menangkap bisa   dihentikan oleh event.cancelBubble = true (IE) atau event.stopPropagation ()   untuk peramban lain.

23
2018-05-14 08:51



Ada juga itu Event.eventPhase properti yang dapat memberi tahu Anda apakah acara tersebut tepat sasaran 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 sudah cuplikan hebat dari jawaban yang diterima, ini adalah output menggunakan eventPhase milik

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>


0
2018-05-29 07:31