ระยะจับเหตุการณ์และระยะ bubbling
ทำความเข้าใจว่าเหตุการณ์เดินทางผ่าน DOM อย่างไร
ระยะจับเหตุการณ์และระยะ bubbling เป็นบทเรียน JavaScript Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน JavaScript Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส JavaScript Academy มีบทเรียนทั้งหมด 4 บทเรียน
การเดินทางสองรอบผ่าน DOM
เมื่อคุณคลิกองค์ประกอบ เหตุการณ์ไม่ได้เกิดขึ้นเฉพาะที่องค์ประกอบนั้น แต่จะเดินทางผ่านต้นไม้ DOM ในสองระยะ: ระยะดักจับ (จากบนลงล่าง จาก document ไปยังเป้าหมาย) และระยะแพร่ขึ้น (จากล่างขึ้นบน จากเป้าหมายกลับไปยัง document)
<div id="outer">
<button id="inner">Click</button>
</div>ค่าเริ่มต้น: การแพร่ขึ้น
โดยค่าเริ่มต้น addEventListener จะรับฟังเหตุการณ์ในระยะแพร่ขึ้น การคลิกปุ่มด้านในจะเรียกตัวจัดการของปุ่มก่อน จากนั้นจึงเรียกตัวจัดการขององค์ประกอบแม่ ต่อด้วยองค์ประกอบปู่ และไล่ขึ้นไปจนถึง document
inner.addEventListener("click", () => console.log("inner"));
outer.addEventListener("click", () => console.log("outer"));
// Click inner -> logs: "inner" then "outer"การเลือกใช้การดักจับ
ส่งอาร์กิวเมนต์ตัวที่สามเป็น true (หรือ { capture: true }) เพื่อรับฟังเหตุการณ์ในระยะดักจับแทน ตัวจัดการในระยะดักจับจะทำงานจากบนลงล่าง ก่อนตัวจัดการในระยะแพร่ขึ้นทั้งหมด
outer.addEventListener("click", () => console.log("outer capture"), true);
inner.addEventListener("click", () => console.log("inner bubble"));
// Click inner -> "outer capture" then "inner bubble"ลำดับทั้งหมด
สำหรับการคลิกที่ #inner ซึ่งมีตัวจัดการในทั้งสองระยะ ลำดับจะเป็นดังนี้: ระยะดักจับจากบนลงล่าง ตามด้วยเป้าหมาย แล้วจึงเป็นระยะแพร่ขึ้นจากล่างขึ้นบน
- การดักจับของ document
- การดักจับของ outer
- inner (เป้าหมาย)
- การแพร่ขึ้นของ outer
- การแพร่ขึ้นของ document
event.target กับ event.currentTarget
event.target คือองค์ประกอบที่ทำให้เกิดเหตุการณ์ขึ้นจริง (จุดที่เกิดการคลิก) ส่วน event.currentTarget คือองค์ประกอบที่ตัวรับฟังเหตุการณ์กำลังทำงานอยู่ ในตัวจัดการขององค์ประกอบแม่ที่เหตุการณ์แพร่ขึ้น ค่าทั้งสองนี้จะแตกต่างกัน
outer.addEventListener("click", (e) => {
console.log(e.target.id); // "inner" - where click occurred
console.log(e.currentTarget.id); // "outer" - listener owner
});การหยุดการแพร่ของเหตุการณ์
event.stopPropagation()จะหยุดการเดินทางของเหตุการณ์ เหตุการณ์จะไม่ไปยังองค์ประกอบถัดไปในระยะปัจจุบัน และตัวจัดการขององค์ประกอบแม่ที่อยู่สูงขึ้นไปในต้นไม้จะไม่ทำงาน
inner.addEventListener("click", (e) => {
e.stopPropagation();
console.log("handled here only");
});
outer.addEventListener("click", () => console.log("never runs"));stopImmediatePropagation
stopPropagation() ยังคงอนุญาตให้ตัวรับฟังอื่น ๆ บนองค์ประกอบเดียวกันทำงานได้ หากต้องการบล็อกตัวรับฟังที่อยู่ร่วมองค์ประกอบเดียวกันด้วย ให้ใช้ event.stopImmediatePropagation()
inner.addEventListener("click", (e) => {
e.stopImmediatePropagation();
console.log("first only");
});
inner.addEventListener("click", () => console.log("blocked"));preventDefault แตกต่างกัน
อย่าสับสนระหว่าง preventDefault() กับ stopPropagation() โดย preventDefault() จะยกเลิกการทำงานเริ่มต้นของเบราว์เซอร์ (เช่น การไปตามลิงก์หรือการส่งแบบฟอร์ม) แต่ NOT หยุดการไหลย้อนขึ้นของเหตุการณ์
link.addEventListener("click", (e) => {
e.preventDefault(); // do not navigate
// event still bubbles to parents
});เหตุใดการดักจับจึงไม่ค่อยใช้
โค้ดส่วนใหญ่ใช้การไหลย้อนขึ้น เพราะตรงกับความเข้าใจโดยทั่วไป กล่าวคือ องค์ประกอบที่ระบุจะตอบสนองก่อน จากนั้นองค์ประกอบบรรจุจึงรับรู้เหตุการณ์ การดักจับมีประโยชน์เมื่อองค์ประกอบแม่ต้องการดักเหตุการณ์หรือยับยั้งเหตุการณ์ก่อนที่องค์ประกอบลูกจะเห็นเหตุการณ์นั้น
การตรวจสอบระยะ
event.eventPhase บอกว่ากำลังอยู่ในระยะใด: 1 คือการดักจับ 2 คือที่เป้าหมาย และ 3 คือการไหลย้อนขึ้น โดยทั่วไปไม่ค่อยจำเป็นต้องใช้ แต่ช่วยได้เมื่อแก้ไขข้อผิดพลาดในสายตัวรับฟังที่ซับซ้อน
el.addEventListener("click", (e) => {
console.log(e.eventPhase); // 1, 2, or 3
}, true);เหตุการณ์ไม่ได้ไหลย้อนขึ้นทั้งหมด
เหตุการณ์ส่วนติดต่อผู้ใช้ส่วนใหญ่ (click, input, keydown) ไหลย้อนขึ้น แต่บางเหตุการณ์จะไม่ทำเช่นนั้นตามค่าเริ่มต้น เช่น focus, blur และ mouseenter สำหรับเหตุการณ์เหล่านี้ ให้ใช้รูปแบบที่ไหลย้อนขึ้น (focusin, focusout) หรือใช้ระยะการดักจับ
ตรวจสอบความเข้าใจ
ทดสอบความเข้าใจเกี่ยวกับระยะของเหตุการณ์
ทบทวน
เหตุการณ์จะเดินทางผ่าน การดักจับ (ลงด้านล่าง) แล้วจึง การไหลย้อนขึ้น (ขึ้นด้านบน) ตัวรับฟังจะใช้การไหลย้อนขึ้นตามค่าเริ่มต้น หากส่ง true จะใช้การดักจับ e.target คือจุดเริ่มต้น ส่วน e.currentTarget คือเจ้าของตัวรับฟัง ใช้ stopPropagation() เพื่อหยุดการเดินทางของเหตุการณ์ และใช้ preventDefault() เพื่อยกเลิกการทำงานเริ่มต้น ทั้งสองระยะนี้เป็นพื้นฐานของการมอบหมายเหตุการณ์
คำถามที่พบบ่อย
บทเรียน “ระยะจับเหตุการณ์และระยะ bubbling” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ระยะจับเหตุการณ์และระยะ bubbling” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส JavaScript Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส JavaScript Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ระยะจับเหตุการณ์และระยะ bubbling”
ทำความเข้าใจว่าเหตุการณ์เดินทางผ่าน DOM อย่างไร คุณปฏิบัติ JavaScript Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน JavaScript Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน JavaScript Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “ระยะจับเหตุการณ์และระยะ bubbling” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน JavaScript Academy นี้ได้ไหม
ได้ บทเรียน JavaScript Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ระยะจับเหตุการณ์และระยะ bubbling
- รูปแบบการมอบหมายเหตุการณ์
- รายการแบบไดนามิกด้วยการมอบหมายเหตุการณ์
- เหตุการณ์กำหนดเอง