Apa perbedaan antara peristiwa yang menggelegak dan menangkap? Kapan sebaiknya menggunakan bubbling vs capturing?
Apa perbedaan antara peristiwa yang menggelegak dan menangkap? Kapan sebaiknya menggunakan bubbling vs capturing?
Jawaban:
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
.
<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 yang div
pertama (klik penangan acara di div
api 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 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 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>
useCapture
sekarang didukung di IE> = 9. sumber
triclkling
sama dengan capturing
? Pembicaraan Crockford dalam pembicaraan Trickling v. Bubbling
video ini - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB sekitar 1 hr 5 minutes
.
trickle down
=> onElement
=>bubble up
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.
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.
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 useCapture
yang 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?
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:
- Peristiwa pertama ditangkap hingga target terdalam, lalu meluap. Di IE <9 mereka hanya menggelembung.
- Semua penangan bekerja di atas panggung menggelegak kecuali
addEventListener
dengan argumen terakhirtrue
, yang merupakan satu-satunya cara untuk menangkap peristiwa pada tahap menangkap.- Bubbling / capturing dapat dihentikan oleh
event.cancelBubble=true
(IE) atauevent.stopPropagation()
untuk browser lain.
Ada juga Event.eventPhase
properti 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 eventPhase
properti
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>