เหตุการณ์ JS เดือดปุดๆ การทำงานขั้นสูงกับวัตถุเหตุการณ์ใน JavaScript ความรู้เบื้องต้นเกี่ยวกับการมอบหมาย

เหตุการณ์คือการกระทำหรือเหตุการณ์ที่เกิดขึ้นในระบบที่คุณกำลังเขียนโปรแกรม ซึ่งระบบจะแจ้งให้คุณทราบ เพื่อให้คุณสามารถตอบสนองต่อสิ่งเหล่านั้นได้ด้วยวิธีใดวิธีหนึ่งหากต้องการ ตัวอย่างเช่น ถ้าผู้ใช้คลิกปุ่มบนเว็บเพจ คุณอาจต้องการตอบสนองต่อการกระทำนั้นด้วยการแสดงกล่องข้อมูล ในบทความนี้ เราจะพูดถึงแนวคิดที่สำคัญบางประการเกี่ยวกับเหตุการณ์ และดูวิธีการทำงานของแนวคิดเหล่านี้ในเบราว์เซอร์ นี่จะไม่ใช่การศึกษาที่ละเอียดถี่ถ้วน แต่เป็นเพียงสิ่งที่คุณจำเป็นต้องรู้ในขั้นตอนนี้

ข้อกำหนดเบื้องต้น: วัตถุประสงค์:
ความรู้คอมพิวเตอร์ขั้นพื้นฐาน ความเข้าใจพื้นฐานเกี่ยวกับ HTML และ CSS ขั้นตอนแรก JavaScript
เพื่อทำความเข้าใจทฤษฎีพื้นฐานของเหตุการณ์ วิธีการทำงานของเบราว์เซอร์ และเหตุการณ์อาจแตกต่างกันในสภาพแวดล้อมการเขียนโปรแกรมต่างๆ
ลำดับเหตุการณ์แห่งความโชคดี

ตามที่กล่าวไว้ข้างต้น เหตุการณ์คือการกระทำหรือเหตุการณ์ที่เกิดขึ้นในระบบที่คุณกำลังเขียนโปรแกรม - ระบบจะสร้าง (หรือ "ยิง") สัญญาณบางอย่างเมื่อมีเหตุการณ์เกิดขึ้น และยังจัดเตรียมกลไกที่การกระทำบางอย่างสามารถทำได้ ดำเนินการโดยอัตโนมัติ (นั่นคือ โค้ดบางส่วนกำลังทำงานอยู่) เมื่อเหตุการณ์เกิดขึ้น ตัวอย่างเช่น ในสนามบินเมื่อทางวิ่งชัดเจนว่าเครื่องบินจะออก สัญญาณจะถูกส่งไปยังนักบิน และผลก็คือ พวกเขาจึงเริ่มขับเครื่องบิน

ในกรณีของเว็บ เหตุการณ์จะเกิดขึ้นภายในหน้าต่างเบราว์เซอร์ และมีแนวโน้มที่จะแนบกับรายการเฉพาะที่อยู่ในนั้น ซึ่งอาจเป็นองค์ประกอบเดียว ชุดขององค์ประกอบ เอกสาร HTML ที่โหลดในแท็บปัจจุบัน หรือ หน้าต่างเบราว์เซอร์ทั้งหมด เหตุการณ์ที่อาจเกิดขึ้นได้มีหลายประเภท เช่น

  • ผู้ใช้คลิกเมาส์เหนือองค์ประกอบบางอย่างหรือวางเคอร์เซอร์ไว้เหนือองค์ประกอบบางอย่าง
  • ผู้ใช้กดปุ่มบนแป้นพิมพ์
  • ผู้ใช้ปรับขนาดหรือปิดหน้าต่างเบราว์เซอร์
  • กำลังส่งแบบฟอร์ม
  • วิดีโอที่กำลังเล่น หรือหยุดชั่วคราว หรือเล่นจนจบ
  • มีข้อผิดพลาดเกิดขึ้น

คุณสามารถรวบรวมจากสิ่งนี้ (และจากการดูข้อมูลอ้างอิงกิจกรรม MDN) ว่ามีกิจกรรมมากมายที่สามารถตอบสนองได้

แต่ละเหตุการณ์ที่มีอยู่จะมีตัวจัดการเหตุการณ์ ซึ่งเป็นบล็อกของโค้ด (โดยปกติแล้วจะเป็นฟังก์ชัน JavaScript ที่คุณในฐานะโปรแกรมเมอร์สร้างขึ้น) ซึ่งจะถูกเรียกใช้เมื่อเหตุการณ์เริ่มทำงาน เมื่อบล็อกของโค้ดถูกกำหนดให้ทำงานเพื่อตอบสนองต่อเหตุการณ์ที่เริ่มทำงาน เราบอกว่าเรากำลังลงทะเบียนตัวจัดการเหตุการณ์ โปรดทราบว่าบางครั้งตัวจัดการเหตุการณ์ถูกเรียกว่าตัวฟังเหตุการณ์ ซึ่งค่อนข้างจะสับเปลี่ยนกันได้สำหรับจุดประสงค์ของเรา แม้ว่าจะพูดอย่างเคร่งครัด แต่ก็ทำงานร่วมกันก็ตาม ผู้ฟังจะคอยฟังเหตุการณ์ที่เกิดขึ้น และตัวจัดการคือโค้ดที่รันเพื่อตอบสนองต่อเหตุการณ์ที่เกิดขึ้น

หมายเหตุ: กิจกรรมบนเว็บไม่ได้เป็นส่วนหนึ่งของภาษา JavaScript หลัก แต่ถูกกำหนดให้เป็นส่วนหนึ่งของ API ที่สร้างไว้ในเบราว์เซอร์

ตัวอย่างง่ายๆ

มาดูตัวอย่างง่ายๆ เพื่ออธิบายสิ่งที่เราหมายถึงที่นี่ คุณเคยเห็นเหตุการณ์และตัวจัดการเหตุการณ์ที่ใช้ในตัวอย่างมากมายในหลักสูตรนี้แล้ว แต่เรามาสรุปเพื่อเสริมความรู้ของเรากัน ต่อไปนี้ตัวอย่าง เรามีอันเดียว ซึ่งเมื่อกดแล้วจะทำให้พื้นหลังเปลี่ยนเป็นสีแบบสุ่ม:

เปลี่ยนสี

ปุ่ม (ระยะขอบ: 10px );

JavaScript มีลักษณะดังนี้:

Const btn = document.querySelector("ปุ่ม"); ฟังก์ชั่นสุ่ม(ตัวเลข) ( return Math.floor(Math.random() * (number+1)); ) btn.onclick = function() ( const rndCol = "rgb(" + Random(255) + "," + สุ่ม(255) + "," + สุ่ม(255) + ")"; document.body.style.พื้นหลังสี = rndCol )

ในโค้ดนี้ เราจัดเก็บการอ้างอิงไปยังปุ่มภายในค่าคงที่ที่เรียกว่า btn โดยใช้ฟังก์ชัน Document.querySelector() นอกจากนี้เรายังกำหนดฟังก์ชันที่ส่งคืนตัวเลขสุ่มด้วย ส่วนที่สามของโค้ดคือตัวจัดการเหตุการณ์ ค่าคงที่ btn ชี้ไปที่องค์ประกอบ และออบเจ็กต์ประเภทนี้มีจำนวนเหตุการณ์ที่สามารถเริ่มทำงานได้ ดังนั้นจึงมีตัวจัดการเหตุการณ์ที่พร้อมใช้งาน เรากำลังรับฟังเหตุการณ์การคลิกโดยการตั้งค่าคุณสมบัติตัวจัดการเหตุการณ์ onclick ให้เท่ากับฟังก์ชันที่ไม่ระบุชื่อซึ่งมีโค้ดที่สร้างสี RGB แบบสุ่มและตั้งค่าสีพื้นหลังให้เท่ากับสีนั้น

รหัสนี้จะถูกรันเมื่อใดก็ตามที่เหตุการณ์การคลิกเริ่มทำงานในองค์ประกอบ นั่นคือเมื่อใดก็ตามที่ผู้ใช้คลิกที่องค์ประกอบนั้น

ผลลัพธ์ตัวอย่างจะเป็นดังนี้:

มันไม่ใช่แค่หน้าเว็บเท่านั้น

อีกสิ่งหนึ่งที่ควรกล่าวถึง ณ จุดนี้ก็คือเหตุการณ์ต่างๆ ไม่ได้มีลักษณะเฉพาะใน JavaScript โดยเฉพาะ ภาษาโปรแกรมส่วนใหญ่จะมี Event Model อยู่บ้าง และวิธีการทำงานของโมเดลก็มักจะแตกต่างไปจากวิถีของ JavaScript จริงๆ แล้ว Event Model ใน JavaScript สำหรับเว็บเพจแตกต่างจากโมเดลเหตุการณ์สำหรับ JavaScript เนื่องจากถูกใช้ในสภาพแวดล้อมอื่น

ตัวจัดการเหตุการณ์แบบอินไลน์ - อย่าใช้สิ่งเหล่านี้

คุณอาจเห็นรูปแบบเช่นนี้ในโค้ดของคุณ:

กดฟังก์ชัน bgChange() ให้ฉัน ( const rndCol = "rgb(" + Random(255) + "," + Random(255) + "," + Random(255) + ")"; document.body.style.wallpaperColor = rndCol )

วิธีแรกสุดในการลงทะเบียนตัวจัดการเหตุการณ์ที่พบบนเว็บเกี่ยวข้องกับแอตทริบิวต์ HTML ของตัวจัดการเหตุการณ์ (หรือตัวจัดการเหตุการณ์แบบอินไลน์) เช่น อันที่หนึ่งแสดงไว้ด้านบน - ค่าแอตทริบิวต์คือโค้ด JavaScript ที่คุณต้องการเรียกใช้เมื่อมีเหตุการณ์เกิดขึ้น ตัวอย่างข้างต้นเรียกใช้ฟังก์ชันที่กำหนดไว้ภายในองค์ประกอบในหน้าเดียวกัน แต่คุณสามารถแทรก JavaScript ลงในแอตทริบิวต์ได้โดยตรง เช่น

กดฉันสิ

คุณสามารถค้นหาแอตทริบิวต์ HTML ที่เทียบเท่าได้สำหรับคุณสมบัติตัวจัดการเหตุการณ์จำนวนมาก อย่างไรก็ตาม คุณไม่ควรใช้สิ่งเหล่านี้ - สิ่งเหล่านี้ถือเป็นแนวปฏิบัติที่ไม่ดี การใช้แอ็ตทริบิวต์ตัวจัดการเหตุการณ์อาจดูเหมือนง่ายหากคุณกำลังทำอะไรบางอย่างอย่างรวดเร็ว แต่กลับกลายเป็นว่าไม่สามารถจัดการได้และไม่มีประสิทธิภาพอย่างรวดเร็ว

ในการเริ่มต้น ไม่ใช่ความคิดที่ดีที่จะผสม HTML และ JavaScript ของคุณเข้าด้วยกัน เนื่องจากการแยกวิเคราะห์ทำได้ยาก - การเก็บ JavaScript ของคุณทั้งหมดไว้ในที่เดียวจะดีกว่า หากอยู่ในไฟล์แยกต่างหาก คุณสามารถนำไปใช้กับเอกสาร HTML หลายชุดได้

แม้จะอยู่ในไฟล์เดียว ตัวจัดการเหตุการณ์แบบอินไลน์ก็ไม่ใช่ความคิดที่ดี ปุ่มเดียวก็โอเค แต่ถ้าคุณมี 100 ปุ่มล่ะ? คุณต้องเพิ่มแอตทริบิวต์ 100 รายการลงในไฟล์ มันจะกลายเป็นการบำรุงรักษาอย่างรวดเร็ว ด้วย JavaScript คุณสามารถเพิ่มฟังก์ชันตัวจัดการเหตุการณ์ให้กับปุ่มทั้งหมดบนหน้าได้อย่างง่ายดายไม่ว่าจะมีกี่ปุ่มก็ตาม โดยใช้บางอย่างเช่น นี้:

ปุ่ม Const = document.querySelectorAll("ปุ่ม"); สำหรับ (ให้ i = 0; i< buttons.length; i++) { buttons[i].onclick = bgChange; } buttons.forEach(function(button) { button.onclick = bgChange; });

หมายเหตุ: การแยกตรรกะการเขียนโปรแกรมออกจากเนื้อหายังช่วยให้ไซต์ของคุณเป็นมิตรกับเครื่องมือค้นหามากขึ้นอีกด้วย

addEventListener() และ RemoveEventListener()

กลไกเหตุการณ์ประเภทใหม่ล่าสุดถูกกำหนดไว้ใน Document Object Model (DOM) Level 2 Events Specification ซึ่งจัดเตรียมฟังก์ชันใหม่ให้กับเบราว์เซอร์ - addEventListener() ฟังก์ชั่นนี้มีลักษณะคล้ายกับคุณสมบัติตัวจัดการเหตุการณ์ แต่ไวยากรณ์แตกต่างอย่างเห็นได้ชัด เราสามารถเขียนตัวอย่างสีแบบสุ่มของเราใหม่ให้มีลักษณะดังนี้:

Const btn = document.querySelector("ปุ่ม"); ฟังก์ชั่น bgChange() ( const rndCol = "rgb(" + สุ่ม(255) + "," + สุ่ม(255) + "," + สุ่ม(255) + ")"; document.body.style.พื้นหลังสี = rndCol; ) btn.addEventListener("คลิก", ​​bgChange);

ภายในฟังก์ชัน addEventListener() เราระบุพารามิเตอร์สองตัว ได้แก่ ชื่อของเหตุการณ์ที่เราต้องการลงทะเบียนตัวจัดการนี้ และโค้ดที่ประกอบด้วยฟังก์ชันตัวจัดการที่เราต้องการเรียกใช้เพื่อตอบสนองต่อฟังก์ชันนั้น โปรดทราบว่าเป็นการเหมาะสมอย่างยิ่งที่จะใส่โค้ดทั้งหมดไว้ในฟังก์ชัน addEventListener() ในฟังก์ชันที่ไม่ระบุชื่อ เช่นนี้

Btn.addEventListener("คลิก", ​​function() ( var rndCol = "rgb(" + สุ่ม(255) + "," + สุ่ม(255) + "," + สุ่ม(255) + ")"; document.body .style.พื้นหลังสี = rndCol);

กลไกนี้มีข้อได้เปรียบเหนือกลไกแบบเก่าที่กล่าวถึงก่อนหน้านี้ ขั้นแรก มีฟังก์ชันคู่กันคือ RemoveEventListener() ซึ่งจะลบ Listener ที่เพิ่มไว้ก่อนหน้านี้ ตัวอย่างเช่น การดำเนินการนี้จะลบ Listener ที่ตั้งค่าไว้ในบล็อกโค้ดแรกในส่วนนี้:

Btn.removeEventListener("คลิก", ​​bgChange);

สิ่งนี้ไม่สำคัญสำหรับโปรแกรมขนาดเล็กที่เรียบง่าย แต่สำหรับโปรแกรมที่ใหญ่กว่าและซับซ้อนกว่านั้น สามารถปรับปรุงประสิทธิภาพในการล้างตัวจัดการเหตุการณ์เก่าที่ไม่ได้ใช้ นอกจากนี้ ยังช่วยให้คุณมีปุ่มเดียวกันในการดำเนินการที่แตกต่างกันในสถานการณ์ที่แตกต่างกัน - สิ่งที่คุณต้องทำคือเพิ่มหรือลบตัวจัดการเหตุการณ์ตามความเหมาะสม

ประการที่สอง คุณยังสามารถลงทะเบียนตัวจัดการหลายตัวสำหรับ Listener เดียวกันได้ ตัวจัดการสองตัวต่อไปนี้จะไม่ถูกนำไปใช้ทั้งคู่:

MyElement.onclick = functionA; myElement.onclick = functionB;

บรรทัดที่สองเขียนทับค่าของ onclick ที่กำหนดโดยบรรทัดแรก สิ่งนี้จะได้ผลอย่างไรก็ตาม:

MyElement.addEventListener("คลิก", ​​functionA); myElement.addEventListener("คลิก", ​​functionB);

ตอนนี้ทั้งสองฟังก์ชันจะทำงานเมื่อมีการคลิกองค์ประกอบ

นอกจากนี้ยังมีฟีเจอร์และตัวเลือกอันทรงพลังอื่นๆ อีกมากมายที่มีให้ในกลไกกิจกรรมนี้ บทความนี้อยู่นอกเหนือขอบเขตเล็กน้อย แต่หากคุณต้องการอ่านข้อมูลเพิ่มเติม โปรดดูที่หน้าอ้างอิง addEventListener() และ RemoveEventListener()

ฉันควรใช้กลไกอะไร?

จากกลไกทั้งสามนี้ คุณไม่ควรใช้แอตทริบิวต์ตัวจัดการเหตุการณ์ HTML อย่างแน่นอน เนื่องจากสิ่งเหล่านี้ล้าสมัยและถือเป็นแนวปฏิบัติที่ไม่ดี ดังที่กล่าวไว้ข้างต้น

อีกสองรายการค่อนข้างใช้แทนกันได้ อย่างน้อยก็สำหรับการใช้งานง่ายๆ:

  • คุณสมบัติตัวจัดการเหตุการณ์มีพลังและตัวเลือกน้อยกว่า แต่มีความเข้ากันได้ข้ามเบราว์เซอร์ที่ดีกว่า (ได้รับการรองรับย้อนหลังไปถึง อินเทอร์เน็ตเอ็กซ์พลอเรอร์ 8). คุณควรเริ่มด้วยสิ่งเหล่านี้ในขณะที่คุณกำลังเรียนรู้
  • เหตุการณ์ DOM ระดับ 2 (addEventListener() ฯลฯ) มีประสิทธิภาพมากกว่า แต่ก็มีความซับซ้อนมากขึ้นและได้รับการรองรับน้อยกว่า (รองรับย้อนกลับไปถึง Internet Explorer 9) คุณควรทดลองใช้สิ่งเหล่านี้และตั้งใจที่จะใช้มันเมื่อเป็นไปได้

ข้อดีหลักของกลไกที่สามคือคุณสามารถลบโค้ดตัวจัดการเหตุการณ์ได้หากจำเป็น โดยใช้ RemoveEventListener() และคุณสามารถเพิ่ม Listener ประเภทเดียวกันหลายรายการลงในองค์ประกอบได้หากจำเป็น ตัวอย่างเช่น คุณสามารถเรียก addEventListener("click", function() ( ... )) บนองค์ประกอบได้หลายครั้ง โดยมีการระบุฟังก์ชันที่แตกต่างกันในอาร์กิวเมนต์ที่สอง สิ่งนี้เป็นไปไม่ได้สำหรับคุณสมบัติตัวจัดการเหตุการณ์ เนื่องจากความพยายามในการตั้งค่าคุณสมบัติในภายหลังจะเขียนทับคุณสมบัติก่อนหน้านี้ เช่น:

องค์ประกอบ.onclick = function1; องค์ประกอบ.onclick = function2; ฯลฯ

หมายเหตุ: หากคุณถูกเรียกให้สนับสนุนเบราว์เซอร์ที่เก่ากว่า Internet Explorer 8 ในการทำงานของคุณ คุณอาจประสบปัญหา เนื่องจากเบราว์เซอร์รุ่นเก่าใช้โมเดลเหตุการณ์ที่แตกต่างจากเบราว์เซอร์รุ่นใหม่ แต่อย่ากลัวเลย ไลบรารี JavaScript ส่วนใหญ่ (เช่น jQuery) มีฟังก์ชันในตัวที่แยกความแตกต่างระหว่างเบราว์เซอร์ออกไป อย่ากังวลเรื่องนี้มากเกินไปในขั้นตอนนี้บนเส้นทางการเรียนรู้ของคุณ

แนวคิดเหตุการณ์อื่นๆ

ในส่วนนี้ เราจะกล่าวถึงแนวคิดขั้นสูงบางส่วนที่เกี่ยวข้องกับกิจกรรมโดยย่อ ในตอนนี้การเข้าใจแนวคิดเหล่านี้อย่างถ่องแท้ไม่ใช่เรื่องสำคัญ แต่แนวคิดเหล่านี้อาจช่วยอธิบายรูปแบบโค้ดบางอย่างที่คุณอาจพบเจอเป็นครั้งคราว

วัตถุเหตุการณ์

บางครั้งภายในฟังก์ชันตัวจัดการเหตุการณ์ คุณอาจเห็นพารามิเตอร์ที่ระบุด้วยชื่อ เช่น event , evt หรือเพียงแค่ e สิ่งนี้เรียกว่าวัตถุเหตุการณ์ และจะถูกส่งผ่านไปยังตัวจัดการเหตุการณ์โดยอัตโนมัติเพื่อให้มีคุณสมบัติและข้อมูลพิเศษ ตัวอย่างเช่น ลองเขียนตัวอย่างสีแบบสุ่มของเราอีกครั้งเล็กน้อย:

ฟังก์ชัน bgChange(e) ( const rndCol = "rgb(" + Random(255) + "," + Random(255) + "," + Random(255) + ")"; e.target.style.พื้นหลังสี = rndCol ; console.log(e); btn.addEventListener("คลิก", ​​bgChange);

ที่นี่คุณจะเห็นว่าเรากำลังรวมวัตถุเหตุการณ์ e ไว้ในฟังก์ชัน และในฟังก์ชันการตั้งค่าสไตล์สีพื้นหลังบน e.target - ซึ่งเป็นปุ่มนั่นเอง คุณสมบัติเป้าหมายของวัตถุเหตุการณ์มักจะอ้างอิงถึงองค์ประกอบที่เหตุการณ์เพิ่งเกิดขึ้น ดังนั้นในตัวอย่างนี้ เรากำลังตั้งค่าสีพื้นหลังแบบสุ่มบนปุ่ม ไม่ใช่หน้าเพจ

หมายเหตุ : คุณสามารถใช้ชื่อใดก็ได้ที่คุณต้องการสำหรับออบเจ็กต์เหตุการณ์ คุณเพียงแค่ต้องเลือกชื่อที่คุณสามารถใช้เพื่ออ้างอิงภายในฟังก์ชันตัวจัดการเหตุการณ์ e/evt/event ถูกใช้บ่อยที่สุดโดยนักพัฒนาเพราะมันสั้นและง่ายต่อการจดจำ เป็นการดีเสมอที่จะรักษาความสม่ำเสมอ ทั้งกับตัวเองและกับคนอื่นๆ หากเป็นไปได้

e.target มีประโยชน์อย่างเหลือเชื่อเมื่อคุณต้องการตั้งค่าตัวจัดการเหตุการณ์เดียวกันบนหลายองค์ประกอบ และดำเนินการบางอย่างกับองค์ประกอบทั้งหมดเมื่อมีเหตุการณ์เกิดขึ้น ตัวอย่างเช่น คุณอาจมีชุดไทล์ 16 ไทล์ที่หายไปเมื่อคลิก การสามารถตั้งค่าให้สิ่งที่หายไปเป็น e.target ได้เสมอ แทนที่จะต้องเลือกด้วยวิธีที่ยากกว่านี้จะมีประโยชน์มาก ในตัวอย่างต่อไปนี้ (ดูที่เป็นประโยชน์-eventtarget.html สำหรับซอร์สโค้ดแบบเต็ม และเห็นซอร์สโค้ดที่ทำงานอยู่ที่นี่ด้วย) เราสร้างองค์ประกอบ 16 รายการโดยใช้ JavaScript จากนั้นเราเลือกทั้งหมดโดยใช้ document.querySelectorAll() จากนั้นวนซ้ำแต่ละอัน โดยเพิ่มตัวจัดการ onclick ให้กับแต่ละอันซึ่งทำให้สีสุ่มถูกนำไปใช้กับแต่ละอันเมื่อคลิก:

Const divs = document.querySelectorAll("div"); สำหรับ (ให้ i = 0; i< divs.length; i++) { divs[i].onclick = function(e) { e.target.style.backgroundColor = bgChange(); } }

ผลลัพธ์มีดังนี้ (ลองคลิกดู - ขอให้สนุก):

ตัวอย่างที่ซ่อน ตัวอย่างเป้าหมายเหตุการณ์ที่มีประโยชน์ div ( height: 100px; width: 25%; float: left; ) for (let i = 1; i DIV > P โดยมีตัวจัดการในแต่ละ:

รหัส: แบบฟอร์ม
กรม

Bubbling ช่วยให้มั่นใจได้ว่าการคลิกที่ด้านใน

จะเรียก onclick handler (ถ้ามี) ก่อนตามจริง

ดังนั้น หากในตัวอย่างด้านบน คุณคลิกที่ P การแจ้งเตือนจะแสดงตามลำดับ: รูปแบบ p → div →

กระบวนการนี้เรียกว่าการขึ้นเนื่องจากเหตุการณ์ "ลอย" จากองค์ประกอบภายในขึ้นไปผ่านผู้ปกครอง เช่นเดียวกับฟองอากาศที่ลอยอยู่ในน้ำ

event.target

ไม่ว่าเราจะจับเหตุการณ์นั้นได้จากองค์ประกอบใด เราก็สามารถทราบได้อย่างชัดเจนว่าเหตุการณ์นั้นเกิดขึ้นที่ใด
องค์ประกอบที่ลึกที่สุดที่ทำให้เกิดเหตุการณ์เรียกว่าองค์ประกอบ "เป้าหมาย" หรือ "แหล่งที่มา" และพร้อมใช้งานเป็น event.target

ความแตกต่างจากสิ่งนี้ (=event.currentTarget):

  • event.target เป็นองค์ประกอบดั้งเดิมที่เกิดเหตุการณ์ขึ้น โดยยังคงไม่เปลี่ยนแปลงในระหว่างกระบวนการเดือดปุด ๆ
  • นี่คือองค์ประกอบปัจจุบันที่เดือดปุด ๆ มาถึงแล้ว

ตัวอย่างเช่น หากมีตัวจัดการ form.onclick เพียงอันเดียว มันจะ "จับ" การคลิกทั้งหมดภายในแบบฟอร์ม เมื่อใดก็ตามที่มีการคลิกภายใน มันจะปรากฏขึ้นไปยังองค์ประกอบที่ตัวจัดการจะทำงาน

ในกรณีนี้:

  • this (=event.currentTarget) จะเป็นฟอร์มของตัวเองเสมอ เนื่องจากตัวจัดการถูกทริกเกอร์
  • event.target จะมีลิงก์ไปยังองค์ประกอบเฉพาะภายในแบบฟอร์ม ซึ่งเป็นองค์ประกอบที่ซ้อนกันมากที่สุดที่เกิดการคลิก

อาจเป็นไปได้ว่า event.target และนี่คือองค์ประกอบเดียวกัน เช่น หากไม่มีแท็กอื่นในแบบฟอร์มและการคลิกอยู่ที่องค์ประกอบนั้นเอง

หยุดยั้งเหตุการณ์ไม่ให้เดือดพล่าน

ทางขึ้นตรงไปด้านบน โดยทั่วไปแล้วเหตุการณ์จะฟองขึ้นและขึ้นที่องค์ประกอบ จากนั้นไปที่ document และบางครั้งก็ถึง window โดยเรียกตัวจัดการทั้งหมดตลอดทาง

แต่ตัวจัดการระดับกลางสามารถตัดสินใจได้ว่าเหตุการณ์ได้รับการประมวลผลอย่างสมบูรณ์แล้วและหยุดการเดือดพล่าน

หากต้องการหยุดการแพร่กระจาย คุณต้องเรียกใช้เมธอด event.stopPropagation()

ตัวอย่างเช่น ที่นี่ เมื่อคลิกปุ่ม ตัวจัดการ body.onclick จะไม่ทำงาน:

รหัส:
คลิกฉัน

การสกัดกั้นเหตุการณ์ เหตุการณ์.stopImmediatePropagation()

หากองค์ประกอบมีตัวจัดการหลายตัวสำหรับเหตุการณ์หนึ่ง แม้ว่าการหยุดเดือดจะเกิดขึ้นก็ตาม แต่ทั้งหมดก็จะถูกดำเนินการ

นั่นคือ stopPropagation ป้องกันไม่ให้เหตุการณ์ก้าวไปข้างหน้า แต่ตัวจัดการทั้งหมดจะทำงานบนองค์ประกอบปัจจุบัน

หากต้องการหยุดการประมวลผลโดยสิ้นเชิง เบราว์เซอร์ที่ทันสมัยสนับสนุนเมธอด event.stopImmediatePropagation() ไม่เพียงป้องกันการเดือดพล่าน แต่ยังหยุดการประมวลผลเหตุการณ์ในองค์ประกอบปัจจุบันอีกด้วย

ความแตกต่าง IE8-

เพื่อให้ง่ายต่อการนำทาง ฉันได้รวบรวมความแตกต่างของ IE8 ที่เกี่ยวข้องกับการแสดงข้อมูลไว้ในส่วนเดียว

ความรู้ของพวกเขาจะจำเป็นหากคุณตัดสินใจเขียนด้วย JS ล้วนๆ โดยไม่มีเฟรมเวิร์ก และคุณต้องการการสนับสนุน IE8

ไม่มีคุณสมบัติ event.currentTarget

โปรดทราบว่าเมื่อกำหนดตัวจัดการผ่านคุณสมบัติ on เรามีสิ่งนี้ ดังนั้นจึงไม่จำเป็นต้องใช้ event.currentTarget ตามกฎ แต่เมื่อกำหนดผ่านแนบEvent ตัวจัดการจะไม่ได้รับสิ่งนี้ ดังนั้นองค์ประกอบปัจจุบัน หากจำเป็น สามารถนำมาจากการปิดเท่านั้น

แทนที่จะใช้ event.target ใน IE8 จะใช้ event.srcElement

หากเรากำลังเขียนตัวจัดการที่จะรองรับทั้ง IE8 และเบราว์เซอร์สมัยใหม่ เราก็สามารถเริ่มต้นได้ดังนี้:

รหัส: elem.onclick = function(event) (
เหตุการณ์ = เหตุการณ์ || หน้าต่าง.เหตุการณ์;
เป้าหมาย var = event.target || เหตุการณ์ srcElement;

// ...ตอนนี้เรามีวัตถุเหตุการณ์และเป้าหมายแล้ว
...
}

หากต้องการหยุดการขึ้น ให้ใช้โค้ด event.cancelBubble=true

คุณสามารถหยุดการเดือดพล่านข้ามเบราว์เซอร์ได้ดังนี้:

รหัส: event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);

ทั้งหมด
  • เมื่อมีเหตุการณ์เกิดขึ้น องค์ประกอบที่เกิดขึ้นจะถูกทำเครื่องหมายเป็น "เป้าหมาย" (event.target)
  • ถัดไป เหตุการณ์จะย้ายลงจากรูทเอกสารไปที่ event.target เป็นครั้งแรก พร้อมทั้งเรียกตัวจัดการที่ส่งผ่าน addEventListener(...., true)
  • ถัดไป เหตุการณ์จะย้ายจาก event.target ไปยังรูทเอกสาร ควบคู่ไปกับการเรียกตัวจัดการที่ส่งผ่าน on* และ addEventListener(...., false)
  • event.target เป็นองค์ประกอบที่ลึกที่สุดที่เกิดเหตุการณ์ขึ้น
  • event.currentTarget (=this) – องค์ประกอบที่ ในขณะนี้ตัวจัดการ (ซึ่งถึงเหตุการณ์) ถูกทริกเกอร์
  • event.eventPhase – ทริกเกอร์ในระยะใด (dive = 1, ascent = 3)
การสกัดกั้นเหตุการณ์

คุณลักษณะที่สำคัญอย่างหนึ่งของภาษาคือการสกัดกั้นเหตุการณ์ หากมีคนคลิกปุ่ม ตัวจัดการเหตุการณ์ onClick ที่สอดคล้องกับปุ่มนั้นจะถูกเรียก ด้วยการจัดการเหตุการณ์ คุณสามารถมั่นใจได้ว่าออบเจ็กต์ที่สอดคล้องกับหน้าต่าง เอกสาร หรือเลเยอร์ของคุณขัดขวางและประมวลผลเหตุการณ์ก่อนที่ตัวจัดการเหตุการณ์จะถูกเรียกเพื่อจุดประสงค์นั้นโดยออบเจ็กต์ปุ่มที่ระบุ ในทำนองเดียวกัน หน้าต่าง เอกสาร หรือออบเจ็กต์เลเยอร์ของคุณสามารถประมวลผลสัญญาณเหตุการณ์ก่อนที่จะถึงปลายทางปกติด้วยซ้ำ
หากต้องการดูว่าสิ่งนี้อาจมีประโยชน์สำหรับอะไร ลองดูตัวอย่างต่อไปนี้:



window.onclick=จัดการ;

ตัวจัดการฟังก์ชั่น (e) (
alert("วัตถุหน้าต่างกำลังขัดขวางเหตุการณ์นี้!");
กลับเป็นจริง; // เช่น. ตามลิงค์
}




คลิกที่ลิงค์นี้

อย่างที่คุณเห็น เราไม่ได้ระบุตัวจัดการเหตุการณ์ในแท็ก - เราเขียนแทน

window.captureEvents (กิจกรรม คลิก);

เพื่อสกัดกั้นเหตุการณ์ คลิกวัตถุหน้าต่าง โดยปกติวัตถุหน้าต่างจะไม่ทำงานกับเหตุการณ์ คลิก- อย่างไรก็ตาม เมื่อสกัดกั้นได้แล้ว เราจะเปลี่ยนเส้นทางไปยังวัตถุหน้าต่าง สังเกตว่าใน กิจกรรม.คลิกส่วน คลิกจะต้องเขียนด้วยตัวพิมพ์ใหญ่ หากคุณต้องการสกัดกั้นเหตุการณ์หลายๆ เหตุการณ์ คุณควรแยกเหตุการณ์เหล่านั้นออกจากกันด้วยสัญลักษณ์ | ตัวอย่างเช่น:

window.captureEvents (Event.CLICK | Event.MOVE);

นอกเหนือจากนี้ในฟังก์ชั่น รับมือ()ซึ่งเราได้กำหนดให้กับบทบาทของตัวจัดการเหตุการณ์ เราใช้คำสั่ง กลับเป็นจริง;- ความหมายที่แท้จริงคือเบราว์เซอร์จะต้องประมวลผลลิงก์เองหลังจากฟังก์ชันเสร็จสมบูรณ์ รับมือ()- ถ้าจะเขียนแทน. กลับเท็จ;แล้วทุกอย่างก็จะจบลง

ถ้าตอนนี้อยู่ในแท็ก คุณจะระบุตัวจัดการเหตุการณ์ บนคลิกคุณจะเข้าใจว่าโปรแกรมนี้จะไม่ถูกเรียกอีกต่อไปเมื่อเหตุการณ์นี้เกิดขึ้น ซึ่งไม่น่าแปลกใจ เนื่องจากวัตถุหน้าต่างดักจับสัญญาณเหตุการณ์ก่อนที่จะถึงวัตถุลิงก์ด้วยซ้ำ หากคุณกำหนดฟังก์ชั่น รับมือ()ยังไง

ตัวจัดการฟังก์ชั่น (e) (
alert("วัตถุหน้าต่างบันทึกเหตุการณ์นี้!");
window.routeEvent (อี);
กลับเป็นจริง;
}

จากนั้นคอมพิวเตอร์จะตรวจสอบว่ามีการกำหนดตัวจัดการเหตุการณ์อื่นสำหรับวัตถุนี้หรือไม่ ตัวแปร e คืออ็อบเจ็กต์เหตุการณ์ของเรา ซึ่งส่งผ่านไปยังฟังก์ชันเหตุการณ์เป็นอาร์กิวเมนต์

นอกจากนี้ คุณยังสามารถส่งสัญญาณเหตุการณ์ไปยังวัตถุได้โดยตรง เมื่อต้องการทำเช่นนี้ คุณสามารถใช้วิธีนี้ได้ จัดการเหตุการณ์()- ดูเหมือนว่านี้:


window.captureEvents (กิจกรรม คลิก);

window.onclick=จัดการ;

ตัวจัดการฟังก์ชั่น (e) (
document.links.handleEvent(e);
}


"คลิก" ที่ลิงค์นี้

ลิงค์ที่สอง

สัญญาณเหตุการณ์การคลิกทั้งหมดจะถูกส่งไปยังลิงก์ที่สองเพื่อประมวลผล - แม้ว่าคุณจะไม่ได้คลิกลิงก์ใด ๆ เลยก็ตาม!

สคริปต์ต่อไปนี้สาธิตวิธีที่สคริปต์ของคุณตอบสนองต่อสัญญาณการกดปุ่ม กดปุ่มใดก็ได้และดูว่าสคริปต์นี้ทำงานอย่างไร


window.captureEvents (กิจกรรม KEYPRESS);

window.onkeypress= กด;

ฟังก์ชั่นที่กด(e) (
alert("กดปุ่ม! ค่า ASCII: " + e.ซึ่ง);
}

ทุกอย่างเริ่มต้นด้วยการใช้ JavaScript และคลาส

อย่างไรก็ตาม ฉันมีปัญหา ฉันต้องการใช้สิ่งที่เรียกว่า Bubble Events แต่ฉันก็ต้องการลดการพึ่งพาที่ฉันต้องแทรกให้เหลือน้อยที่สุดด้วย ฉันไม่ต้องการรวมไลบรารี jQuery สำหรับ "การทดสอบเล็กๆ น้อยๆ นี้" เพียงเพื่อใช้ฟองอากาศของเหตุการณ์

เรามาดูรายละเอียดกันดีกว่าว่าเหตุการณ์ Toast คืออะไร ทำงานอย่างไร และวิธีนำไปใช้บางส่วน

โอเค แล้วมีปัญหาอะไรล่ะ? ลองดูตัวอย่างง่ายๆ:

สมมติว่าเรามีรายการปุ่มต่างๆ ทุกครั้งที่ฉันคลิกที่หนึ่งในนั้น มันควรจะกลายเป็น "ใช้งานอยู่" หลังจากกดอีกครั้งปุ่มจะกลับสู่สถานะเดิม

เริ่มต้นด้วย HTML:

  • ดินสอ
  • ปากกา
  • ยางลบ

ฉันสามารถใช้ตัวจัดการเหตุการณ์ JavaScript มาตรฐานเช่นนี้:

สำหรับ(var i = 0; i< buttons.length; i++) { var button = buttons[i]; button.addEventListener("click", function() { if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); }); }
ดูดี... แต่มันใช้งานไม่ได้ อย่างน้อยก็ไม่ใช่ในแบบที่เราคาดหวัง

การปิดชนะ สำหรับผู้ที่รู้ JavaScript เพียงเล็กน้อยปัญหาก็ชัดเจน

ส่วนที่เหลือ ผมจะอธิบายสั้นๆ - ฟังก์ชันตัวจัดการถูกล็อคไว้ที่ตัวแปรของปุ่ม อย่างไรก็ตาม นี่เป็นตัวแปรเดียว และจะถูกเขียนทับทุกการวนซ้ำ

ในการวนซ้ำครั้งแรก ตัวแปรจะอ้างอิงถึงปุ่มแรก ในอันถัดไป - ถึงอันที่สองและอื่น ๆ แต่เมื่อผู้ใช้คลิกที่ปุ่ม การวนซ้ำได้สิ้นสุดลงแล้ว และตัวแปรของปุ่มจะอ้างอิงถึงปุ่มสุดท้าย ซึ่งจะเรียกตัวจัดการเหตุการณ์ทุกครั้ง ความผิดปกติ

สิ่งที่เราต้องการคือบริบทที่แยกจากกันสำหรับแต่ละฟังก์ชัน:

ปุ่ม Var = document.querySelectorAll(".toolbar button"); var createToolbarButtonHandler = function(ปุ่ม) ( return function() ( if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); ); สำหรับ (var i = 0; i< buttons.length; i++) { buttons[i].addEventListener("click", createToolBarButtonHandler(buttons[i])); }
ดีขึ้นมาก! และที่สำคัญที่สุดคือมันทำงานได้อย่างถูกต้อง เราได้สร้างฟังก์ชัน createToolbarButtonHandle ที่ส่งคืนตัวจัดการเหตุการณ์ จากนั้นเราจะแนบตัวจัดการของเราเองสำหรับแต่ละปุ่ม

แล้วปัญหาคืออะไร? มันดูดีและใช้งานได้ดี อย่างไรก็ตาม เรายังสามารถทำให้โค้ดของเราดีขึ้นได้

อันดับแรก เราสร้างตัวจัดการมากเกินไป สำหรับแต่ละปุ่มภายใน .toolbar เราจะสร้างฟังก์ชันและผูกมันไว้เป็นตัวจัดการเหตุการณ์ สำหรับปุ่มสามปุ่ม การใช้งานหน่วยความจำนั้นน้อยมาก

แต่ถ้าเรามีสิ่งเช่นนี้:

  • ฟู
  • บาร์
  • // ...อีก 997 องค์ประกอบ...
  • บาซ

แน่นอนว่าคอมพิวเตอร์จะไม่ระเบิดจากการล้น อย่างไรก็ตาม การใช้หน่วยความจำของเรายังห่างไกลจากอุดมคติ เราจัดสรรมันเป็นจำนวนมาก แม้ว่าเราจะสามารถทำได้หากไม่มีมันก็ตาม มาเขียนโค้ดของเราใหม่อีกครั้งเพื่อให้เราสามารถใช้ฟังก์ชันเดียวกันได้หลายครั้ง

แทนที่จะอ้างอิงตัวแปรปุ่มเพื่อติดตามว่าปุ่มไหนที่เราคลิก เราสามารถใช้ออบเจ็กต์เหตุการณ์ ซึ่งจะถูกส่งผ่านเป็นอาร์กิวเมนต์แรกไปยังตัวจัดการเหตุการณ์แต่ละตัว

ออบเจ็กต์เหตุการณ์มีข้อมูลบางอย่างเกี่ยวกับเหตุการณ์ ในกรณีของเรา เราสนใจฟิลด์ currentTarget จากนั้นเราจะได้ลิงก์ไปยังองค์ประกอบที่ถูกคลิก:

แถบเครื่องมือ VarButtonHandler = function(e) ( ปุ่ม var = e.currentTarget; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active" ); สำหรับ (var i = 0; i< buttons.length; i++) { button.addEventListener("click", toolbarButtonHandler); }
ยอดเยี่ยม! ไม่เพียงแต่เราทำให้ทุกอย่างง่ายขึ้นเหลือเพียงฟังก์ชันเดียวที่ใช้หลายครั้งเท่านั้น เรายังทำให้โค้ดของเราอ่านง่ายขึ้นโดยการลบฟังก์ชันตัวสร้างที่ไม่จำเป็นออก

อย่างไรก็ตาม เรายังสามารถทำได้ดีกว่านี้

สมมติว่าเราได้เพิ่มปุ่มบางปุ่มลงในชีตหลังจากที่โค้ดของเราทำงานแล้ว จากนั้นเราจะต้องเพิ่มตัวจัดการเหตุการณ์ให้กับแต่ละรายการด้วย และเราจะต้องเก็บลิงก์ไปยังตัวจัดการนี้และลิงก์จากที่อื่น ดูไม่น่าดึงดูดเกินไป

อาจมีแนวทางอื่นอีกหรือไม่?

มาเริ่มด้วยการทำความเข้าใจว่าเหตุการณ์ทำงานอย่างไรและดำเนินไปอย่างไรตาม DOM ของเรา

ส่วนใหญ่ทำงานอย่างไร? เมื่อผู้ใช้คลิกที่องค์ประกอบ เหตุการณ์จะถูกสร้างขึ้นเพื่อแจ้งให้แอปพลิเคชันทราบเกี่ยวกับเรื่องนี้ การเดินทางของแต่ละเหตุการณ์เกิดขึ้นในสามขั้นตอน:
  • ขั้นตอนการสกัดกั้น
  • เหตุการณ์เกิดขึ้นบนองค์ประกอบเป้าหมาย
  • ระยะขึ้น
  • หมายเหตุ: ไม่ใช่ทุกเหตุการณ์ที่จะผ่านขั้นตอนการสกัดกั้นหรือฟองสบู่ บางเหตุการณ์จะถูกสร้างขึ้นในองค์ประกอบทันที อย่างไรก็ตาม นี่เป็นข้อยกเว้นของกฎมากกว่า

    เหตุการณ์ถูกสร้างขึ้นภายนอกเอกสาร จากนั้นจึงย้ายตามลำดับชั้น DOM ไปยังองค์ประกอบเป้าหมาย เมื่อบรรลุเป้าหมายแล้ว เหตุการณ์จะถูกดึงมาจากองค์ประกอบ DOM ในลักษณะเดียวกัน

    นี่คือเทมเพลต HTML ของเรา:

    • ปุ่ม A
    • ปุ่มบี
    • ปุ่ม C

    เมื่อผู้ใช้คลิกที่ปุ่ม A เหตุการณ์จะดำเนินไปดังนี้:

    เริ่ม
    - #เอกสาร
    - ขั้นตอนการสกัดกั้น
    - HTML
    - ร่างกาย
    - แอล
    - ลี#li_1
    - ปุ่ม A< - Событие возникает для целевого элемента
    - ระยะขึ้น
    - ลี#li_1
    - แอล
    - ร่างกาย
    - HTML
    วี#เอกสาร

    โปรดสังเกตว่าเราสามารถติดตามเส้นทางที่เหตุการณ์ใช้เพื่อไปถึงองค์ประกอบเป้าหมายได้ ในกรณีของเรา สำหรับการกดปุ่มแต่ละปุ่ม เรามั่นใจได้ว่าเหตุการณ์จะเด้งกลับขึ้นมา โดยผ่านองค์ประกอบแม่ - ul เราสามารถใช้สิ่งนี้และใช้งานป๊อปอัปเหตุการณ์ได้

    เหตุการณ์บับเบิ้ล เหตุการณ์บับเบิ้ลคือเหตุการณ์ที่แนบกับองค์ประกอบหลัก แต่จะดำเนินการเฉพาะเมื่อเป็นไปตามเงื่อนไขบางประการเท่านั้น

    ลองใช้แถบเครื่องมือของเราเป็นตัวอย่างที่เป็นรูปธรรม:

    ชั้น Ul = "แถบเครื่องมือ">

  • ดินสอ
  • ปากกา
  • ยางลบ

  • ตอนนี้เรารู้แล้วว่าการคลิกปุ่มใด ๆ จะปรากฏขึ้นผ่านองค์ประกอบ ul.toolbar ให้แนบตัวจัดการเหตุการณ์ของเราไปกับมัน โชคดีที่เรามีมันอยู่แล้ว:

    แถบเครื่องมือ Var = document.querySelector(".toolbar"); toolbar.addEventListener("คลิก", ​​function(e) ( var button = e.target; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList. ลบ("ใช้งานอยู่" ));
    ตอนนี้เรามีโค้ดที่สะอาดกว่ามาก และเรายังกำจัดการวนซ้ำอีกด้วย! อย่างไรก็ตาม โปรดทราบว่าเราได้แทนที่ e.currentTarget ด้วย e.target เหตุผลก็คือเราประมวลผลกิจกรรมในระดับที่แตกต่างกัน

    e.target คือเป้าหมายที่แท้จริงของเหตุการณ์ โดยที่เหตุการณ์จะผ่าน DOM และที่ที่เหตุการณ์จะเกิดขึ้น
    e.currentTarget - องค์ประกอบปัจจุบันที่จัดการเหตุการณ์ ในกรณีของเรา นี่คือ ul.toolbar

    ปรับปรุงเหตุการณ์ป๊อปอัป ขณะนี้เราจัดการการคลิกแต่ละองค์ประกอบที่ปรากฏขึ้นผ่าน ul.toolbar แต่เงื่อนไขการทดสอบของเราง่ายเกินไป จะเกิดอะไรขึ้นถ้าเรามี DOM ที่ซับซ้อนมากขึ้นซึ่งมีไอคอนและองค์ประกอบที่ไม่ได้ออกแบบมาให้คลิกได้

    • ดินสอ
    • ปากกา
    • ยางลบ

    อ๊ะ! ตอนนี้เมื่อเราคลิกที่ li.separator หรือไอคอน เราจะเพิ่มคลาส .active เข้าไป อย่างน้อยที่สุดนี่ก็ไม่ดี เราต้องการวิธีกรองเหตุการณ์เพื่อให้เราตอบสนองต่อองค์ประกอบที่เราต้องการ

    มาสร้างฟังก์ชันตัวช่วยเล็กๆ ขึ้นมาสำหรับสิ่งนี้:

    Var delegate = function(criteria, Listener) ( return function(e) ( var el = e.target; do ( if (!criteria(el)) Continue; e.delegateTarget = el; Listener.apply(this, arguments); กลับ; ) ในขณะที่((el = el.parentNode));
    ผู้ช่วยของเราทำสองสิ่ง ขั้นแรก มันจะวนซ้ำแต่ละองค์ประกอบและพาเรนต์ของมัน และตรวจสอบว่าเป็นไปตามเงื่อนไขที่ส่งในพารามิเตอร์เกณฑ์หรือไม่ หากองค์ประกอบเป็นไปตามที่ต้องการ ตัวช่วยจะเพิ่มฟิลด์ให้กับออบเจ็กต์เหตุการณ์ที่เรียกว่า delegateTarget ซึ่งจัดเก็บองค์ประกอบที่ตรงตามเงื่อนไขของเรา แล้วจึงเรียกผู้ดูแล ดังนั้น หากไม่มีองค์ประกอบใดที่ตรงตามเงื่อนไข ก็จะไม่มีการเรียกตัวจัดการ

    เราสามารถใช้มันได้ดังนี้:

    แถบเครื่องมือ Var = document.querySelector(".toolbar"); var ButtonFilter = function(elem) ( return elem.classList && elem.classList.contains("btn"); ); var buttonHandler = function(e) ( ปุ่ม var = e.delegateTarget; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active" ); toolbar.addEventListener("คลิก", ​​มอบหมาย (buttonsFilter, buttonHandler));
    สิ่งที่แพทย์สั่ง: ตัวจัดการเหตุการณ์หนึ่งตัวแนบกับองค์ประกอบเดียวที่ทำงานทั้งหมด แต่มันทำเฉพาะกับองค์ประกอบที่เราต้องการเท่านั้น และตอบสนองอย่างสมบูรณ์แบบต่อการเพิ่มและการลบวัตถุออกจาก DOM

    สรุป เราดูโดยสรุปเกี่ยวกับพื้นฐานของการดำเนินการเหตุการณ์การมอบหมาย (การจัดการป๊อปอัป) ใน JavaScript ล้วนๆ นี่เป็นสิ่งที่ดีเพราะเราไม่จำเป็นต้องสร้างและแนบตัวจัดการจำนวนมากสำหรับแต่ละองค์ประกอบ

    หากฉันต้องการสร้างไลบรารี่หรือใช้โค้ดในการพัฒนา ฉันจะเพิ่มบางสิ่ง:

    ฟังก์ชันตัวช่วยสำหรับการตรวจสอบว่าวัตถุตรงตามเกณฑ์ในรูปแบบที่เป็นหนึ่งเดียวและใช้งานได้มากขึ้นหรือไม่ ชอบ:

    เกณฑ์ Var = ( isElement: function(e) ( return e instanceof HTMLElement; ), hasClass: function(cls) ( return function(e) ( return allowance.isElement(e) && e.classList.contains(cls); ) ) //เกณฑ์เพิ่มเติม);
    การใช้ผู้ช่วยบางส่วนก็มีประโยชน์เช่นกัน:

    Var partialDelgate = function(criteria) ( return function(handler) ( return delgate(criteria, handler); ) );
    บทความต้นฉบับ: การทำความเข้าใจเหตุการณ์ JavaScript ที่ได้รับมอบหมาย
    (จากผู้แปล: คนแรกของฉัน ตัดสินอย่างเคร่งครัด)

    ขอให้มีความสุขในการเขียนโค้ด!

    ในบทนี้ เราจะทำความคุ้นเคยกับแนวคิดเรื่องเหตุการณ์เดือดปุด ๆ และยังดูว่าจะสามารถขัดจังหวะได้อย่างไร นอกจากนี้ เราจะได้ทราบว่ากิจกรรมจะต้องผ่านขั้นตอนอื่นๆ ใดบ้างก่อนที่จะเริ่มปรากฏ

    บับเบิ้ลเหตุการณ์

    หากมีเหตุการณ์เกิดขึ้นกับองค์ประกอบบางอย่าง องค์ประกอบนั้นจะเริ่ม "ป๊อปอัป" เช่น เกิดขึ้นในพ่อแม่ แล้วก็ในปู่ย่าตายาย ฯลฯ

    ตามมาว่าเหตุการณ์ที่สร้างโดยองค์ประกอบบางอย่างสามารถดักจับได้โดยใช้ตัวจัดการบนพาเรนต์ ปู่ย่าตายาย ฯลฯ

    เราจะสาธิตการเกิดขึ้นของเหตุการณ์ (ฟองสบู่) โดยใช้ตัวอย่างต่อไปนี้:

    หัวเรื่อง

    ข้อความที่สำคัญมากบางข้อความ

    บท

    ข้อความบางส่วน

    ข้อความที่เหลือ

    มาเขียนสคริปต์เล็ก ๆ ซึ่งเราจะเพิ่มตัวจัดการเหตุการณ์ "คลิก" สำหรับองค์ประกอบของหน้าทั้งหมดรวมถึงเอกสารและวัตถุหน้าต่าง

    document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); สำหรับ (var i=0; i< allElements.length; i++) { allElements[i].addEventListener("click",function() {console.log(this.tagName);},false); }; document.addEventListener("click",function() {console.log(this);},false); window.addEventListener("click",function() {console.log(this);},false); });

    มาสร้างหน้า HTML และแทรกโค้ด HTML ด้านบนลงไป สคริปต์ที่เขียนใน จาวาสคริปต์ให้แทรกก่อนแท็กเนื้อหาปิด หลังจากนั้นให้เปิดเพจที่สร้างขึ้นใหม่ในเว็บเบราว์เซอร์ กดปุ่ม F12 แล้วไปที่คอนโซล ตอนนี้เรามาคลิกซ้ายในพื้นที่ที่เป็นขององค์ประกอบที่แข็งแกร่งแล้วดูว่ากิจกรรมจะปรากฏขึ้นมาอย่างไร

    วิธีขัดจังหวะเหตุการณ์เดือดปุดๆ

    การเพิ่มขึ้นของเหตุการณ์ (ฟองสบู่) สามารถถูกขัดจังหวะได้ ในกรณีนี้ เหตุการณ์นี้จะไม่ถูกทริกเกอร์สำหรับองค์ประกอบที่สูงกว่า (ระดับบนสุด) วิธีการที่ออกแบบมาเพื่อหยุดการแพร่กระจายของเหตุการณ์ (บับเบิล) เรียกว่า stopPropagation()

    ตัวอย่างเช่น ลองเปลี่ยนตัวอย่างของเราด้านบนเพื่อให้เหตุการณ์ไม่ปรากฏอยู่เหนือเนื้อหา: document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); for (var i=0 ; ฉัน

    ไม่ต้องสงสัยเลยว่าพื้นผิวมีความสะดวกและโปร่งใสทางสถาปัตยกรรม อย่าหยุดมันเว้นแต่จำเป็นจริงๆ

    รับองค์ประกอบที่เรียกว่าตัวจัดการ

    เพื่อให้ได้องค์ประกอบ DOM (วัตถุ) ที่เรียกว่าตัวจัดการเหตุการณ์ คุณต้องใช้คำสำคัญนี้ คีย์เวิร์ดนี้ (นี้) ใช้ได้เฉพาะในตัวจัดการหากคุณสมัครรับข้อมูลกิจกรรมโดยใช้ JavaScript

    ตัวอย่างเช่น เรามาแสดง id ขององค์ประกอบที่เรียกว่าตัวจัดการเหตุการณ์ในคอนโซล:

    วาร์ myP = document.getElementById("myP"); myP.addEventListener("click",function())( //get the DOM element that called the event handler - this //get it its id and output it to the console console.log(this.id); ));

    คุณยังสามารถใช้คุณสมบัติ currentTarget (event.currentTarget) เพื่อรับองค์ประกอบปัจจุบัน

    ขั้นตอน (ระยะ) ของเหตุการณ์

    ก่อนที่เหตุการณ์จะเริ่มเกิดขึ้น (ระยะการขึ้น) ก่อนอื่นจะต้องผ่านอีก 2 ด่าน:

    • ขั้นที่ 1 คือขั้นของการดื่มด่ำกับองค์ประกอบที่ทำให้เกิดเหตุการณ์ เหล่านั้น. ในระยะนี้จะมีการเคลื่อนตัวจากบนลงล่างคือ จากวัตถุหน้าต่างไปยังองค์ประกอบ อีกด้วย เวทีนี้เรียกอีกอย่างว่าขั้นตอนการสกัดกั้น
    • ระยะที่ 2 คือระยะของการบรรลุเป้าหมาย เช่น องค์ประกอบ (วัตถุ) ที่สร้างเหตุการณ์

    เมื่อพิจารณาถึงขั้นตอนทั้งหมดที่เหตุการณ์ดำเนินไป จะเกิดภาพต่อไปนี้:

    มาแก้ไขสคริปต์ตัวอย่างข้างต้นดังนี้:

    Document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); สำหรับ (var i=0; i

    พารามิเตอร์ตัวที่สามของเมธอด addEventListener และ RemoveEventListener จะกำหนดระยะที่เหตุการณ์จะถูกตรวจจับ หากพารามิเตอร์นี้เป็นจริง เหตุการณ์จะถูกดักจับที่ระยะเหตุการณ์แช่ (สกัดกั้น) และหากพารามิเตอร์เป็น false เหตุการณ์จะถูกดักจับที่ระยะฟองสบู่ ในการจัดการเหตุการณ์บนเป้าหมาย คุณสามารถใช้เมธอด addEventListener ที่มีค่าเท็จหรือค่าจริงก็ได้

    ข้อควรสนใจ: ในระหว่างขั้นตอนการแช่ (สกัดกั้น) เหตุการณ์จะถูกดักจับโดยตัวจัดการที่เพิ่มโดยใช้เมธอด addEventListener() เท่านั้น ตัวจัดการที่เพิ่มด้วยวิธีการอื่น (แอตทริบิวต์ HTML หรือผ่าน JavaScript โดยใช้คุณสมบัติ on[event]) สามารถสกัดกั้นเหตุการณ์ได้เฉพาะในขั้นตอนที่เดือดปุด ๆ เท่านั้น

    รับองค์ประกอบที่สร้างเหตุการณ์

    เพื่อให้ได้องค์ประกอบเป้าหมายเช่น องค์ประกอบที่สร้างเหตุการณ์ต้องใช้คุณสมบัติเป้าหมาย (event.target)

    ลองพิจารณาตัวอย่างข้างต้น ซึ่งเราเปลี่ยนเนื้อหาขององค์ประกอบสคริปต์ดังต่อไปนี้:

    Document.addEventListener("DOMContentLoaded", function() ( var elementBody = document.body; elementBody.addEventListener("click",function())( console.log(this.tagName + " - องค์ประกอบที่เรียกว่าตัวจัดการ") ; console .log(event.currentTarget.tagName + " - องค์ประกอบที่เรียกว่าตัวจัดการ"); console.log(event.target.tagName + " - องค์ประกอบที่สร้างเหตุการณ์" ),false);

    เรามาสาธิตตัวอย่างของเราโดยคลิกซ้ายในพื้นที่ที่เป็นขององค์ประกอบที่แข็งแกร่ง: