อะไรคือความแตกต่างระหว่างเหตุการณ์เดือดและการจับ? เมื่อใดที่หนึ่งควรใช้ bubbling vs capture
อะไรคือความแตกต่างระหว่างเหตุการณ์เดือดและการจับ? เมื่อใดที่หนึ่งควรใช้ bubbling vs capture
คำตอบ:
การทำ bubbling และการจับกิจกรรมเป็นสองวิธีในการเผยแพร่เหตุการณ์ใน HTML DOM API เมื่อเหตุการณ์เกิดขึ้นในองค์ประกอบภายในองค์ประกอบอื่นและองค์ประกอบทั้งสองได้ลงทะเบียนหมายเลขอ้างอิงสำหรับเหตุการณ์นั้นแล้ว โหมดการขยายพันธุ์เหตุการณ์กำหนดในคำสั่งซื้อองค์ประกอบได้รับเหตุการณ์
ด้วย bubbling เหตุการณ์จะถูกจับและจัดการโดยองค์ประกอบด้านในสุดก่อนแล้วจึงแพร่กระจายไปยังองค์ประกอบด้านนอก
เมื่อจับภาพเหตุการณ์จะถูกจับครั้งแรกโดยองค์ประกอบนอกสุดและแพร่กระจายไปยังองค์ประกอบภายใน
การจับภาพนั้นเรียกอีกอย่างว่า "trickling" ซึ่งช่วยในการจำลำดับการแพร่กระจาย:
หยดลงมา
ย้อนกลับไปในสมัยก่อน Netscape สนับสนุนการจับภาพเหตุการณ์ขณะที่ Microsoft เลื่อนตำแหน่งการจัดกิจกรรม ทั้งสองเป็นส่วนหนึ่งของมาตรฐานเหตุการณ์วัตถุจำลองเอกสาร W3C (2000)
IE <9 ใช้เฉพาะเหตุการณ์เดือดขณะที่ IE9 + และเบราว์เซอร์หลักทั้งหมดรองรับทั้งสองอย่าง ในทางกลับกันประสิทธิภาพของการขัดถูเหตุการณ์อาจลดลงเล็กน้อยสำหรับ DOM ที่ซับซ้อน
เราสามารถใช้addEventListener(type, listener, useCapture)เพื่อลงทะเบียนตัวจัดการเหตุการณ์สำหรับใน bubbling (ค่าเริ่มต้น) หรือโหมดการจับภาพ trueการใช้รูปแบบการจับภาพผ่านอาร์กิวเมนต์ที่สามเป็น
<div>
<ul>
<li></li>
</ul>
</div>
ในโครงสร้างด้านบนสมมติว่ามีเหตุการณ์การคลิกเกิดขึ้นในliองค์ประกอบ
ในการจับภาพรูปแบบการจัดกิจกรรมจะได้รับการจัดการโดยdivครั้งแรก (คลิกจัดการเหตุการณ์ในdivจะยิงครั้งแรก) จากนั้นในแล้วที่สุดท้ายในองค์ประกอบเป้าหมายulli
ในรูปแบบ bubbling สิ่งที่ตรงกันข้ามจะเกิดขึ้น: เหตุการณ์จะได้รับการจัดการเป็นครั้งแรกจากliนั้นตามด้วยulและในที่สุดจะเป็นdivองค์ประกอบ
สำหรับข้อมูลเพิ่มเติมโปรดดู
ในตัวอย่างด้านล่างหากคุณคลิกที่องค์ประกอบใด ๆ ที่ไฮไลต์คุณจะเห็นว่าขั้นตอนการดักจับของโฟลว์การกระจายเหตุการณ์เกิดขึ้นก่อนตามด้วยเฟสเดือดปุด ๆ
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
useCaptureรองรับตอนนี้ใน IE> = 9. source
triclklingเช่นเดียวกับcapturing? พูดคุยเกี่ยวกับครอกTrickling v. Bubblingในการพูดคุยวิดีโอนี้ - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB1 hr 5 minutesรอบ
trickle down=> onElement=>bubble up
รายละเอียด:
quirksmode.orgมีคำอธิบายที่ดีเกี่ยวกับเรื่องนี้ สรุป (คัดลอกมาจาก quirksmode):
การจับภาพเหตุการณ์
เมื่อคุณใช้การจับภาพเหตุการณ์
| | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | -----------------------------------ตัวจัดการเหตุการณ์ของ element1 ยิงก่อนตัวจัดการเหตุการณ์ขององค์ประกอบ 2 จะยิงครั้งสุดท้าย
เหตุการณ์เดือดปุด ๆ
เมื่อคุณใช้เดือดปุด ๆ เหตุการณ์
/ \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | -----------------------------------ตัวจัดการเหตุการณ์ขององค์ประกอบ 2 ยิงก่อนตัวจัดการเหตุการณ์ขององค์ประกอบ 1 จะยิงครั้งสุดท้าย
จะใช้อะไรดี?
ขึ้นอยู่กับสิ่งที่คุณต้องการจะทำ ไม่มีอะไรดีไปกว่านี้แล้ว ความแตกต่างคือลำดับของการเรียกใช้งานตัวจัดการเหตุการณ์ เวลาส่วนใหญ่มันจะเป็นการดีที่จะยิงตัวจัดการเหตุการณ์ในระยะเดือดแต่มันก็เป็นสิ่งจำเป็นที่จะยิงพวกเขาก่อนหน้านี้
หากมีสององค์ประกอบองค์ประกอบที่ 1 และองค์ประกอบที่ 2 องค์ประกอบที่ 2 อยู่ในองค์ประกอบที่ 1 และเราแนบตัวจัดการเหตุการณ์ที่มีทั้งสององค์ประกอบให้พูด onClick ตอนนี้เมื่อเราคลิกที่องค์ประกอบ 2 แล้ว eventHandler สำหรับองค์ประกอบทั้งสองจะถูกดำเนินการ ตอนนี้คำถามคือลำดับเหตุการณ์ที่จะดำเนินการ หากเหตุการณ์ที่แนบมากับองค์ประกอบ 1 ดำเนินการครั้งแรกจะเรียกว่าการจับภาพเหตุการณ์และหากเหตุการณ์ที่แนบมากับองค์ประกอบ 2 ดำเนินการครั้งแรกนี้เรียกว่าเหตุการณ์เดือดปุด ๆ ตาม W3C เหตุการณ์จะเริ่มขึ้นในช่วงการจับภาพจนกว่าจะถึงเป้าหมายกลับมาที่องค์ประกอบจากนั้นจะเริ่มเดือด
สถานะการดักจับและการเดือดกำลังเป็นที่รู้จักโดยพารามิเตอร์ useCapture ของเมธอด addEventListener
eventTarget.addEventListener (ชนิด, ฟัง [useCapture]);
โดยค่าเริ่มต้น useCapture เป็นเท็จ มันหมายความว่ามันอยู่ในช่วงเดือดปุด ๆ
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>
โปรดลองเปลี่ยนจริงและเท็จ
the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubblingเกี่ยวกับ ฉันพบเพียง addEventListenerมีพารามิเตอร์useCaptureที่สามารถตั้งค่าเป็นจริงหรือเท็จ และใน HTML 4.0, ฟังเหตุการณ์ที่ถูกระบุว่าเป็นลักษณะขององค์ประกอบuseCapture defaults to falseและ คุณสามารถลิงค์ไปยังข้อมูลจำเพาะที่ยืนยันสิ่งที่คุณเขียนได้หรือไม่?
ฉันได้พบบทช่วยสอนนี้ที่ javascript.infoอย่างชัดเจนในการอธิบายหัวข้อนี้ และการสรุป 3 คะแนนในตอนท้ายพูดถึงประเด็นสำคัญอย่างยิ่ง ฉันพูดที่นี่:
- เหตุการณ์แรกจะถูกจับลงไปที่เป้าหมายที่ลึกที่สุดจากนั้นทำให้เกิดฟองขึ้น ใน IE <9 พวกเขามี แต่ฟองสบู่เท่านั้น
- ตัวจัดการทั้งหมดทำงานบนสเตจที่เดือดปุด ๆ ยกเว้น
addEventListenerอาร์กิวเมนต์สุดท้ายtrueซึ่งเป็นวิธีเดียวที่จะจับเหตุการณ์บนสเตจเก็บภาพ- Bubbling / capture สามารถหยุดได้โดย
event.cancelBubble=true(IE) หรือevent.stopPropagation()สำหรับเบราว์เซอร์อื่น
นอกจากนี้ยังมีEvent.eventPhaseคุณสมบัติที่สามารถบอกคุณได้ว่าเหตุการณ์เป็นไปตามเป้าหมายหรือมาจากที่อื่น
โปรดทราบว่ายังไม่ได้กำหนดความเข้ากันได้ของเบราว์เซอร์ ฉันทดสอบบน Chrome (66.0.3359.181) และ Firefox (59.0.3) และรองรับที่นั่น
การขยายตัวอย่างที่ยอดเยี่ยมจากคำตอบที่ยอมรับแล้วนี่คือผลลัพธ์โดยใช้eventPhaseคุณสมบัติ
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>
เดือด
Event propagate to the upto root element is **BUBBLING**.
จับ
Event propagate from body(root) element to eventTriggered Element is **CAPTURING**.