เรียนรู้ว่า Event Delegation ใน JavaScript คืออะไร ทำไมต้องใช้ และใช้อย่างไร
JavaScript Event Delegation คืออะไร และควรใช้เมื่อไหร่?
โดยสรุป Event Delegation เป็นวิธีของ JavaScript ที่ช่วยให้คุณโต้ตอบกับอิลีเมนต์ลูก (child elements) โดยใช้ เพียง event listener เดียว บนอิลีเมนต์พาเรนต์ (parent element) ด้วย Event Delegation คุณสามารถหลีกเลี่ยงการเพิ่ม event handlers ให้ทุกอิลีเมนต์ลูก แต่ยังคงค้นหาและจัดการพวกเขาได้
คุณจะเห็นว่านี่ทรงพลังอย่างไรในทันที
สมมติว่าคุณมีรายการรายการภายในรายการ เมื่อผู้ใช้คลิกที่รายการใดรายการหนึ่ง คุณต้องการให้เกิดอะไรขึ้น
มาดู 2 วิธีที่แตกต่างกันในการทำสิ่งนี้
แนบ event listeners ให้แต่ละอิลีเมนต์
วิธีทั่วไปในการเข้าถึงรายการอิลีเมนต์แต่ละตัวในรายการคือวนลูปผ่านพวกเขา เช่น ด้วยลูป for แล้วแนบ event listeners ให้แต่ละอิลีเมนต์:
let allExerciseItems = document.querySelectorAll(".exercise-item") for (let exerciseItem of allExerciseItems) { exerciseItem.addEventListener("click", function(event) { // Do something with target child element event.target.classList.toggle("exercise-complete") }); }
ตัวอย่าง
https://codepen.io/StrengthandFreedom/pen/KBZezV/
เข้าถึงรายการด้วย Event Delegation
Event Delegation แตกต่างจากตัวอย่างลูป for ที่คุณเห็นข้างบนสิ้นสุด แทนที่จะวนลูป (iterate) ผ่านแต่ละอิลีเมนต์ที่เราต้องการเข้าถึง เราเพียงเป้าหมายอิลีเมนต์พาเรนต์ เพียงอย่างเดียว:
// Get parent element, add a click event listener document.querySelector(".exercise-list").addEventListener("click", function(event) { if(event.target.classList.contains('exercise-item')) { // Do something with target child element event.target.classList.toggle('exercise-complete') } })
ตัวอย่าง CodePen หมายเหตุ: แทน classList.contains คุณสามารถใช้ API matches() ของ element.matches หากต้องการความยืดหยุ่นของตัวเลือกมากขึ้น
เช่นที่คุณเห็น ผลลัพธ์เหมือนกันทุกประการ เมื่อคุณคลิกที่รายการออกกำลังกายใดรายการหนึ่ง พวกเขาจะ toggle คลาส exercise-complete สิ่งที่แตกต่างคือวิธีที่เราใช้เพื่อให้ได้ผลลัพธ์นี้
ทำไมคุณควรใช้วิธี Event Delegation แทนวิธี Event handling + for loop?
มาอภิปรายต่อไป!
Event Delegation และประสิทธิภาพ
ลองจินตนาการว่าคุณกำลังจัดการกับเว็บแอปพลิเคชันที่มีอิลีเมนต์ที่สร้างขึ้นแบบไดนามิกหลายร้อยหรือหลายพัน ต่อวัน ชั่วโมง หรือแม้แต่นาที ตัวอย่างอาจเป็นปฏิทินจองห้องพักโรงแรม หรือแพลตฟอร์มโซเชียลมีเดียอย่าง Twitter ที่ต้องการอัปเดตแบบสดบ่อยครั้งเพื่อประสบการณ์ผู้ใช้ที่ดีที่สุด
หากทุกอิลีเมนต์ใน UI เว็บของคุณมี event listeners แนบอยู่ สถานการณ์แบบนี้จะกลายเป็น hardware intensive ได้อย่างรวดเร็ว
Event listeners ทั้งหมดนั้นอาจ佔 CPU ของผู้ใช้ พวกเขาอาจทำให้เกิด function references จำนวนมหาศาลนั่งอยู่ในหน่วยความจำ สาเหตุหนึ่งของ memory leaks และการลดประสิทธิภาพทั่วไป
ผมไม่รู้มากเกี่ยวกับ GC (Garbage Collection) ผมมีโชคที่เขียน JavaScript (ภาษาโปรแกรมมิ่งระดับสูง) มากกว่าแทบทั้งหมด แต่สิ่งหนึ่งที่ผมรู้คือ GC ในเบราว์เซอร์อาจเป็นไปไม่ได้ตามที่คาดหมาย เนื่องจากเบราว์เซอร์ผู้ขายที่หลากหลาย (Chrome, FireFox ฯลฯ) และอุปกรณ์นับไม่ถ้วน (สมาร์ทโฟน, โน้ตบุ๊ค ฯลฯ)
Garbage Collection
โดยสรุป Garbage Collection เป็นประเภทหนึ่งของการจัดการหน่วยความจำของคอมพิวเตอร์ Garbage collector พยายามลบโค้ดเก่า/ไม่ได้ใช้งานที่แค่นั่งอยู่และใช้หน่วยความจำของคอมพิวเตอร์ มี garbage collectors ที่แตกต่างกันมากมายสำหรับภาษาโปรแกรมมิ่งและระบบต่างๆ
การมี event listeners แนบอยู่กับทุกอย่าง ตามที่เห็นในตัวอย่างลูป จะเพิ่มปริมาณ garbage collection ที่เว็บแอปของคุณต้องการ ซึ่งจะเกือบแน่นอนลดประสิทธิภาพลง
โดยทั่วไปจะมีประสิทธิภาพมากกว่าเมื่อคุณมี event listener เพียงตัวเดียว บนอิลีเมนต์พาเรนต์ ที่ฟังการคลิกทั้งหมดบนอิลีเมนต์ลูกของมัน แทนที่จะแนบ event listeners ให้ทุกอิลีเมนต์ลูกเดี่ยวๆ