หากคุณใช้กรอบการเขียนที่น้อยลงเช่น jQuery คุณจะมีโอกาสน้อยที่จะดีน้อยที่ JS พื้นเมือง
Xiaocai ไม่ต้องการเขียนบล็อกนี้ดูเหมือนว่าจะเป็นพื้นฐานมาก แต่เมื่อเห็นว่าเธอไม่สามารถอธิบายการผูกพันและการรื้อถอนเหตุการณ์ JS พื้นเมืองบนอินเทอร์เน็ตได้เธอตัดสินใจที่จะสร้างวิทยาศาสตร์ยอดนิยม
ก่อนอื่น Xiaocai ไม่รู้จักมากนักเพียงแบ่งปันความคิดของฉันกับคุณ
โมเดลเหตุการณ์ DOM0
แบบจำลองเหตุการณ์มีการพัฒนาอย่างต่อเนื่องและโมเดลเหตุการณ์ในช่วงต้นเรียกว่าระดับ DOM0
โมเดลเหตุการณ์ DOM0 รองรับโดยเบราว์เซอร์ทั้งหมด
การลงทะเบียนชื่อเหตุการณ์โดยตรงบนวัตถุ DOM คือวิธีการเขียน DOM0 เช่น:
การคัดลอกรหัสมีดังนี้:
document.getElementById ("ทดสอบ"). onclick = function (e) {};
มันหมายถึงการลงทะเบียนเหตุการณ์ onclick แน่นอนว่ามันมีความหมายเช่นเดียวกับการเขียนนี้:
การคัดลอกรหัสมีดังนี้:
document.getElementById ("ทดสอบ") ["Onmousemove"] = function (e) {};
นี่คืออะไรมันเป็นเพียงสองวิธีในการเข้าถึงคุณสมบัติวัตถุ JS รูปแบบของ [] ส่วนใหญ่เพื่อแก้ปัญหาที่ชื่อแอตทริบิวต์ไม่ใช่ตัวระบุทางกฎหมาย ตัวอย่างเช่น Object.123 ต้องรายงานข้อผิดพลาด แต่วัตถุ ["123"] หลีกเลี่ยงปัญหานี้ ในเวลาเดียวกันการเขียน [] ยังเขียน JS Alive โดยใช้สตริงเพื่อแสดงชื่อแอตทริบิวต์ซึ่งสามารถผูกเหตุการณ์แบบไดนามิกได้ที่รันไทม์
กลับไปที่จุดเมื่อเหตุการณ์ถูกทริกเกอร์พารามิเตอร์ E จะถูกส่งผ่านโดยค่าเริ่มต้นเพื่อแสดงวัตถุเหตุการณ์ ผ่าน E เราสามารถรับข้อมูลที่เป็นประโยชน์มากมายเช่นพิกัดของการคลิกองค์ประกอบ DOM ที่เรียกเหตุการณ์โดยเฉพาะ ฯลฯ
จากเหตุการณ์ DOM0 สำหรับโหนด DOM เดียวกันสามารถลงทะเบียนได้เพียงหนึ่งเดียวและเหตุการณ์เดียวกันที่ลงทะเบียนในภายหลังจะแทนที่เหตุการณ์ที่ลงทะเบียนก่อนหน้านี้ ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
var btn = document.getElementById ("ทดสอบ");
btn.onmousemove = function (e) {
การแจ้งเตือน ("ตกลง");
-
btn ["Onmousemove"] = function (e) {
การแจ้งเตือน ("OK1");
-
ผลลัพธ์จะส่งออก OK1
มาพูดถึงเรื่องนี้ต่อไป เมื่อเหตุการณ์ถูกเรียกใช้สิ่งนี้หมายถึงวัตถุ DOM ที่เหตุการณ์ถูกเรียกใช้ ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
var btn = document.getElementById ("ทดสอบ");
btn.onmousemove = function (e) {
การแจ้งเตือน (this.id);
-
การทดสอบผลลัพธ์ผลลัพธ์ เนื่องจากเหตุการณ์ได้รับการลงทะเบียนบนโหนด DOM พร้อมการทดสอบ ID เมื่อเหตุการณ์ถูกทริกเกอร์หลักสูตรนี้แสดงถึงโหนด DOM นี้ สามารถเข้าใจได้ว่าเหตุการณ์นี้ถูกเรียกโดยโหนด DOM นี้
ดังนั้นจึงค่อนข้างง่ายที่จะยกเลิกเหตุการณ์ คุณจะต้องลงทะเบียนกิจกรรมอีกครั้งและตั้งค่าเป็น NULL ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
var btn = document.getElementById ("ทดสอบ");
btn.onclick = function (e) {
การแจ้งเตือน ("ตกลง");
-
btn.onclick = null;
หลักการคือเหตุการณ์ที่ลงทะเบียนล่าสุดจะต้องเขียนทับเหตุการณ์ก่อนหน้านี้ ตั้งค่ากิจกรรมที่ลงทะเบียนล่าสุดเป็น NULL ซึ่งจะยกเลิกเหตุการณ์
เรื่องนี้ยังไม่จบและรูปแบบเหตุการณ์ DOM0 ยังเกี่ยวข้องกับเหตุการณ์ที่เขียนโดยตรงใน HTML ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
<div id = "ทดสอบ" onclick = "exec ();" > </div>
เหตุการณ์ที่ลงทะเบียนด้วยวิธีนี้ยังทำตามหลักการครอบคลุมและสามารถลงทะเบียนได้เพียงครั้งเดียวและเหตุการณ์สุดท้ายจะมีผล
ความแตกต่างคือเหตุการณ์ที่ลงทะเบียนด้วยวิธีนี้เทียบเท่ากับการเรียกฟังก์ชั่นแบบไดนามิก (วิธีการประเมินค่อนข้าง) ดังนั้นวัตถุเหตุการณ์จะไม่ถูกส่งผ่านในเวลาเดียวกันชี้ไปที่หน้าต่างและไม่ใช่วัตถุ DOM อีกต่อไปที่กระตุ้นเหตุการณ์
โมเดลเหตุการณ์ DOM2
เมื่อเทียบกับ DOM0, Shouca เข้าใจสองจุดต่อไปนี้เท่านั้น:
・ DOM2 รองรับการลงทะเบียนของหลาย ๆ เหตุการณ์เดียวกันด้วยองค์ประกอบ DOM เดียวกัน
・ DOM2 ได้เพิ่มแนวคิดของการจับภาพและเดือด
เหตุการณ์ DOM2 ได้รับการจัดการโดย AddEventListener และ RemoveVentListener แน่นอนว่านี่คือมาตรฐาน
อย่างไรก็ตาม IE8 และเบราว์เซอร์ต่อไปนี้ได้สร้างสิ่งที่แนบมาและ detachevent ที่สอดคล้องกัน เนื่องจาก Xiaocai ไม่ได้ตั้งใจเล็กน้อยบทความนี้จะไม่พูดคุยกัน
AddeventListener เป็นเหตุการณ์การลงทะเบียน มันมีสามพารามิเตอร์คือ: "ชื่อเหตุการณ์", "การโทรกลับเหตุการณ์" และ "Capture/Bubble" ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
var btn = document.getElementById ("ทดสอบ");
btn.addeventListener ("คลิก", ฟังก์ชั่น (e) {
การแจ้งเตือน ("ตกลง");
}, เท็จ);
ไม่จำเป็นต้องพูดชื่อเหตุการณ์ไม่มากเกินไป เมื่อเทียบกับ DOM0 ก่อนหน้านี้จะถูกลบออก
การโทรกลับของเหตุการณ์นั้นง่ายต่อการเข้าใจ คุณต้องแจ้งให้คุณทราบหากเหตุการณ์ถูกทริกเกอร์! เมื่อโทรกลับเช่น DOM0 พารามิเตอร์เหตุการณ์จะถูกส่งผ่านโดยค่าเริ่มต้น ในเวลาเดียวกันสิ่งนี้หมายถึงโหนด DOM ที่กระตุ้นเหตุการณ์
พารามิเตอร์สุดท้ายคือประเภทบูลีนจริงแสดงถึงเหตุการณ์การจับภาพและเท็จแสดงถึงเหตุการณ์ฟอง จริงๆแล้วมันง่ายที่จะเข้าใจ ก่อนอื่นทำไดอะแกรม:
หมายความว่าหากองค์ประกอบกระตุ้นเหตุการณ์สิ่งแรกที่ได้รับแจ้งคือหน้าต่างและจากนั้นเอกสารและไปตามลำดับจนกว่าองค์ประกอบ (องค์ประกอบเป้าหมาย) ที่กระตุ้นเหตุการณ์จริง กระบวนการนี้คือการจับภาพ ถัดไปเหตุการณ์จะฟองจากองค์ประกอบเป้าหมายจากนั้นออกตามลำดับจนถึงวัตถุหน้าต่าง กระบวนการนี้เป็นฟอง
ทำไมต้องออกแบบวิธีนี้? สิ่งนี้น่าจะเกิดจากต้นกำเนิดทางประวัติศาสตร์ที่ลึกซึ้งดังนั้น Xiaocai จึงไม่รู้อะไรมากเกี่ยวกับเรื่องนี้ดังนั้นเธอจึงไม่พูดเรื่องไร้สาระ
จากนี้เราจะเห็นได้ว่าเหตุการณ์การจับภาพจะเกิดขึ้นก่อนเหตุการณ์ฟองสบู่
สมมติว่ามีโครงสร้าง HTML เช่นนี้:
การคัดลอกรหัสมีดังนี้:
<div id = "ทดสอบ">
<div id = "testinner"> </div>
</div>
จากนั้นเราลงทะเบียนกิจกรรมคลิกสองครั้งใน DIV ด้านนอกคือเหตุการณ์การจับภาพและเหตุการณ์เดือดร้อนรหัสมีดังนี้:
การคัดลอกรหัสมีดังนี้:
var btn = document.getElementById ("ทดสอบ");
// จับกิจกรรม
btn.addeventListener ("คลิก", ฟังก์ชั่น (e) {
การแจ้งเตือน ("OK1");
}, จริง);
// เหตุการณ์เดือด
btn.addeventListener ("คลิก", ฟังก์ชั่น (e) {
การแจ้งเตือน ("ตกลง");
}, เท็จ);
ในที่สุดคลิกที่ Div ภายในป๊อปอัพ OK1 ก่อนแล้วจึงปรากฏขึ้นตกลง เมื่อรวมกับแผนภาพแผนผังด้านบน DIV ด้านนอกนั้นเทียบเท่ากับร่างกายในรูปและ DIV ด้านในเทียบเท่ากับ DIV ด้านล่างในรูปพิสูจน์ว่าเหตุการณ์การจับกุมจะถูกดำเนินการก่อนแล้วเหตุการณ์ฟองจะถูกดำเนินการ
ทำไมต้องเน้นการคลิกที่ div ภายใน? เนื่องจากองค์ประกอบ DOM ที่กระตุ้นให้เกิดเหตุการณ์จะต้องมาจากชั้นในและองค์ประกอบชั้นนอก DOM มีโอกาสจำลองและจับเหตุการณ์และเหตุการณ์ฟองซึ่งสามารถมองเห็นได้จากแผนภาพแผนผัง
ถ้าคุณลงทะเบียนเหตุการณ์การจับภาพและเหตุการณ์เดือดในองค์ประกอบ DOM ที่ก่อให้เกิดเหตุการณ์จริง
โครงสร้าง HTML นั้นเหมือนกับด้านบนและรหัส JS มีดังนี้:
การคัดลอกรหัสมีดังนี้:
var btninner = document.getElementById ("testinner");
// เหตุการณ์เดือด
btninner.addeventListener ("คลิก" ฟังก์ชัน (e) {
การแจ้งเตือน ("ตกลง");
}, เท็จ);
// จับกิจกรรม
btninner.addeventListener ("คลิก" ฟังก์ชัน (e) {
การแจ้งเตือน ("OK1");
}, จริง);
แน่นอนคลิกที่ div ด้านในและผลลัพธ์ก็คือ OK First Up Up ขึ้นมาจากนั้น OK1 ในทางทฤษฎีเหตุการณ์การจับภาพควรถูกเรียกใช้ก่อนนั่นคือ OK1 ปรากฏขึ้นก่อน แต่นี่เป็นพิเศษเพราะเราลงทะเบียนเหตุการณ์ในองค์ประกอบ DOM ที่ทริกเกอร์เหตุการณ์จริงซึ่งเทียบเท่ากับการลงทะเบียนใน DIV ในรูป จากรูปเราจะเห็นได้ว่าองค์ประกอบ DOM ที่ทริกเกอร์เหตุการณ์จริง ๆ คือจุดสิ้นสุดของเหตุการณ์การจับภาพและจุดเริ่มต้นของเหตุการณ์ฟองดังนั้นจึงไม่มีความแตกต่างระหว่างเหตุการณ์ที่นี่ อันไหนลงทะเบียนก่อนการดำเนินการอันที่หนึ่ง ในตัวอย่างนี้เหตุการณ์ฟองได้รับการลงทะเบียนก่อนดังนั้นจึงจะดำเนินการก่อน
หลักการนี้ใช้กับหลายเหตุการณ์ในแบบเดียวกัน ตัวอย่างเช่นหากมีการลงทะเบียนเหตุการณ์ฟองสบู่ 3 ครั้งในครั้งเดียวคำสั่งการดำเนินการจะอยู่ในลำดับของการลงทะเบียนการลงทะเบียนครั้งแรกและการดำเนินการครั้งแรก ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
var btninner = document.getElementById ("testinner");
btninner.addeventListener ("คลิก" ฟังก์ชัน (e) {
การแจ้งเตือน ("ตกลง");
}, เท็จ);
btninner.addeventListener ("คลิก" ฟังก์ชัน (e) {
การแจ้งเตือน ("OK1");
}, เท็จ);
btninner.addeventListener ("คลิก" ฟังก์ชัน (e) {
การแจ้งเตือน ("OK2");
}, เท็จ);
ผลที่ได้คือแน่นอน OK, OK1 และ OK2 Pop-Ups
เพื่อที่จะเข้าใจรูปแบบเหตุการณ์เพิ่มเติมมีสถานการณ์อื่น หาก Div ด้านนอกและ Inner Div ลงทะเบียนเหตุการณ์การจับภาพในเวลาเดียวกันเมื่อคลิกที่ DIV ด้านในเหตุการณ์ DIV ด้านนอกจะต้องถูกเรียกใช้ก่อน รหัสมีดังนี้:
การคัดลอกรหัสมีดังนี้:
var btn = document.getElementById ("ทดสอบ");
var btninner = document.getElementById ("testinner");
btninner.addeventListener ("คลิก" ฟังก์ชัน (e) {
การแจ้งเตือน ("ตกลง");
}, จริง);
btn.addeventListener ("คลิก", ฟังก์ชั่น (e) {
การแจ้งเตือน ("OK1");
}, จริง);
ผลที่ได้คือ OK1 ปรากฏขึ้นก่อน
หากทั้ง Div ด้านนอกและ DIV ด้านในเป็นเหตุการณ์ฟองที่ลงทะเบียนเมื่อคลิกที่ DIV ภายในเหตุการณ์ DIV ภายในจะต้องดำเนินการก่อนและหลักการก็เหมือนกัน
ผู้อ่านอย่างระมัดระวังจะพบว่าสำหรับกรณีของการทำรัง Div หากคุณคลิกที่ Div ด้านใน Div ด้านนอกจะก่อให้เกิดเหตุการณ์ซึ่งดูเหมือนจะเป็นปัญหา!
การคลิกนั้นชัดเจนว่าเป็น div ภายใน แต่เหตุการณ์ DIV ด้านนอกก็ถูกกระตุ้นเช่นกันซึ่งเป็นปัญหาอย่างแท้จริง
ในความเป็นจริงเมื่อเหตุการณ์ถูกทริกเกอร์วัตถุเหตุการณ์จะถูกส่งผ่านโดยค่าเริ่มต้น ดังที่ได้กล่าวไว้ก่อนหน้านี้มีวิธีการเกี่ยวกับวัตถุเหตุการณ์นี้: การหยุดยั้ง ด้วยวิธีนี้สามารถป้องกันฟองอากาศได้เพื่อให้ Div ด้านนอกจะไม่ได้รับเหตุการณ์ รหัสมีดังนี้:
การคัดลอกรหัสมีดังนี้:
var btn = document.getElementById ("ทดสอบ");
var btninner = document.getElementById ("testinner");
btn.addeventListener ("คลิก", ฟังก์ชั่น (e) {
การแจ้งเตือน ("OK1");
}, เท็จ);
btninner.addeventListener ("คลิก" ฟังก์ชัน (e) {
// หยุดฟองสบู่
E.StopPropagation ();
การแจ้งเตือน ("ตกลง");
}, เท็จ);
ในที่สุดฉันต้องพูดคุยเกี่ยวกับวิธีแก้ไขเหตุการณ์ ไวยากรณ์ที่ไม่ได้รับ: btn.removeeVentListener ("ชื่อเหตุการณ์", "การโทรกลับเหตุการณ์", "Capture/Bubble");
นี่เป็นเช่นเดียวกับพารามิเตอร์ของเหตุการณ์ที่มีผลผูกพันตามที่อธิบายไว้ในรายละเอียด:
・ ชื่อของเหตุการณ์หมายถึงการยกเลิกเหตุการณ์
・ การโทรกลับเหตุการณ์เป็นฟังก์ชั่นซึ่งจะต้องเหมือนกับฟังก์ชั่นที่ลงทะเบียนเหตุการณ์
・ ประเภทเหตุการณ์ค่าบูลีนซึ่งจะต้องสอดคล้องกับประเภทเมื่อมีการลงทะเบียนเหตุการณ์
กล่าวอีกนัยหนึ่งชื่อการโทรกลับและพิมพ์ร่วมกันตัดสินใจว่าจะยกเลิกเหตุการณ์ใดที่ขาดไม่ได้ ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
var btn = document.getElementById ("ทดสอบ");
// จัดเก็บการโทรกลับในตัวแปร
var fn = function (e) {
การแจ้งเตือน ("ตกลง");
-
//ผูกพัน
btn.addeventListener ("คลิก", fn, false);
// การกำจัด
btn.removeeVentListener ("คลิก", fn, false);
เพื่อให้เหตุการณ์ที่ลงทะเบียนถูกยกเลิกฟังก์ชันการโทรกลับจะต้องถูกบันทึกไว้มิฉะนั้นจะไม่สามารถยกเลิกได้
ผสม DOM0 และ DOM2
สิ่งต่าง ๆ ยุ่งอยู่แล้วและนี่คือการใช้งานที่หลากหลายซึ่งทำให้ผู้คนมีชีวิตอยู่ - -
อย่ากลัวมันไม่มีปัญหาที่จะใช้ในลักษณะที่หลากหลาย โมเดล DOM0 และโมเดล DOM2 แต่ละตัวทำตามกฎของตนเองและไม่ส่งผลกระทบต่อกันและกัน
โดยรวมแล้วไม่มีอะไรอื่นหากลงทะเบียนก่อนและดำเนินการก่อน
postscript
ณ จุดนี้เหตุการณ์ JS พื้นเมืองเกือบจะเสร็จสิ้นแล้ว Xiaocai รู้เรื่องนี้เท่านั้น ผู้อ่านสามารถเพิ่มคะแนนความรู้อื่น ๆ ได้
ในแอปพลิเคชันจริงผู้เชี่ยวชาญจริงจะไม่ลงทะเบียนเหตุการณ์มากมายอย่างโง่เขลา โดยทั่วไปคุณจะต้องลงทะเบียนเหตุการณ์ในองค์ประกอบ DOM นอกสุดจากนั้นใช้กลไกการจับภาพและฟองเพื่อค้นหาองค์ประกอบ DOM ที่กระตุ้นเหตุการณ์จริงและในที่สุดก็เรียกการโทรกลับตามข้อมูลที่จัดทำโดยองค์ประกอบ DOM ที่กระตุ้นเหตุการณ์
กล่าวอีกนัยหนึ่งผู้เชี่ยวชาญจะจัดการเหตุการณ์ด้วยตนเองโดยไม่ต้องพึ่งพาเบราว์เซอร์เพื่อจัดการพวกเขาซึ่งสามารถปรับปรุงประสิทธิภาพและสร้างความมั่นใจได้ นี่ไม่ใช่สิ่งที่ jQuery ทำหรือไม่
ตกลงการสอนจบลงที่นี่ฉันหวังว่ามันจะเป็นประโยชน์กับผู้อ่าน!