เมื่อเร็ว ๆ นี้ฉันกำลังเขียนกรอบ JavaScript ฉันเพิ่งห่อหุ้มเหตุการณ์ Domcontentloaded และฉันก็ตื่นเต้นเล็กน้อย ฉันจดบันทึกเกี่ยวกับหลักการและปัญหาความเข้ากันได้ที่พบในระหว่างกระบวนการพัฒนาเพื่อหลีกเลี่ยงการลืมทุกที่
เมื่อเราเขียนรหัส JS เรามักจะเพิ่มเหตุการณ์ Window.onLoad ส่วนใหญ่ใช้ GetElementById, GetElementsByTagname และวิธีอื่น ๆ เพื่อเลือกองค์ประกอบ DOM สำหรับการทำงานหลังจากโหลด DOM อย่างไรก็ตาม window.load จะรอจนกว่า DOM สคริปต์ CSS จะถูกโหลดและทรัพยากรทั้งหมดในภาพหรือแม้กระทั่ง iframe จะถูกทริกเกอร์ ในหลายกรณีหน้าเว็บมีรูปภาพมากขึ้นและมีขนาดใหญ่ขึ้น ใช้เวลานานในการโหลดภาพและเห็นได้ชัดว่าสายเกินไปที่จะเรียกใช้งาน JS ซึ่งมักจะส่งผลกระทบต่อประสบการณ์ผู้ใช้
เฟรมเวิร์ก JS จำนวนมากมีฟังก์ชั่นเอกสารพร้อมใช้งานเช่นวิธีการ $ (เอกสาร) ของ jQuery. ready () ซึ่งสามารถเรียกใช้รหัส JS ได้ทันทีหลังจากโหลด DOM เพื่อให้สามารถโหลดภาพได้อย่างช้าๆ
หลักของ document.ready คือเหตุการณ์ Domcontentloaded Firefox, Chrome, Opera, Safari และ IE9+ ทั้งหมดสามารถใช้ addeventListener ('Domcontentloaded', FN, FALSE) สำหรับการผูกเหตุการณ์ IE6 ~ 8 ไม่รองรับเหตุการณ์ Domcontentloaded ดังนั้นการประมวลผลความเข้ากันได้ควรดำเนินการสำหรับ IE6 ~ 8
ข้อมูลบอกว่า IE6 ~ 8 สามารถใช้ document.onreadyStateChange เหตุการณ์เพื่อฟังว่าสถานะ Document.readyState เท่ากับจะเสร็จสมบูรณ์เพื่อตรวจสอบว่ามีการโหลด DOM หรือไม่ หาก IFRAME ถูกฝังอยู่ในหน้าเอกสาร ReadyState ของ IE6 ~ 8 จะรอจนกว่าทรัพยากรทั้งหมดใน iframe จะถูกโหลดก่อนที่จะเสร็จสมบูรณ์ ในเวลานี้ iframe จะกลายเป็นผู้ใช้หลักที่ใช้เวลานาน แต่หลังจากการทดสอบแม้ว่าจะไม่มี iframe ในหน้าเมื่อ ReadyState เท่ากับเหตุการณ์ ONLOAD จะถูกทริกเกอร์จริงแทนที่จะเป็นเหตุการณ์ DomcontentLoaded ซึ่งน่าแปลกใจไปที่จุดนี้
โชคดีที่มีวิธีการ Doscroll ที่เป็นเอกลักษณ์ เมื่อไม่ได้โหลดหน้าเว็บจะมีการรายงานข้อผิดพลาดเมื่อมีการเรียกวิธี Doscroll ในทางกลับกันตราบใดที่ Doscroll ถูกเรียกในช่วงเวลาจนกว่าจะไม่มีการรายงานข้อผิดพลาดนั่นหมายความว่าเพจ DOM ได้รับการโหลด วิธีนี้ถูกต้องไม่ว่าเนื้อหาในรูปภาพและ iframe จะถูกโหลดหรือไม่
หากไฟล์ JS หลายไฟล์ถูกผูกไว้กับเหตุการณ์ที่พร้อมใช้งานเพื่อป้องกันไม่ให้เบราว์เซอร์มีผลผูกพันและดำเนินการซ้ำ ๆ ในลักษณะที่เป็นระเบียบกลไกการคิวเหตุการณ์สามารถนำมาใช้เพื่อแก้ปัญหาได้
ข้างต้นเป็นหลักการและปัญหาความเข้ากันได้ของเหตุการณ์ที่พร้อมใช้งาน ต่อไปนี้เป็นย่อหน้าของรหัสตัวอย่าง เพื่ออำนวยความสะดวกในการทำความเข้าใจกระบวนการดำเนินการกระบวนการดำเนินการถูกเขียนในความคิดเห็นโดยใช้โหมดการห่อหุ้มฟังก์ชั่น หากมีความไม่เหมาะสมใด ๆ โปรดให้คำแนะนำกับฉัน
การคัดลอกรหัสมีดังนี้:
// บันทึกคิวเหตุการณ์ของ DomReady
Eventqueue = [];
// ตัดสินว่ามีการโหลด DOM หรือไม่
พร้อม = false;
// ตัดสินว่า domready ถูกผูกไว้หรือไม่
ISBIND = FALSE;
/*ดำเนินการ domready ()
-
*@param {function}
*@Execute ผลักดันตัวจัดการเหตุการณ์ไปยังคิวเหตุการณ์และผูก domcontentloaded
* หากการโหลด DOM เสร็จสมบูรณ์ให้ดำเนินการทันที
*@ผู้โทร
-
ฟังก์ชั่น domready (fn) {
ถ้า (พร้อม) {
fn.call (หน้าต่าง);
-
อื่น{
Eventqueue.push (FN);
-
bindready ();
-
/*การผูกเหตุการณ์ domready
-
*@param null
*@Execute Modern Browsers Bind DomcontentLoaded ผ่าน Addevlistener รวมถึง IE9+
IE6-8 กำหนดว่า DOM นั้นถูกโหลดโดยการตัดสิน Doscroll
*@caller domready ()
-
ฟังก์ชั่น bindready () {
ถ้า (พร้อม) กลับมา;
ถ้า (isbind) กลับ;
isBind = true;
if (window.addeventListener) {
document.addeventListener ('domcontentloaded', execfn, false);
-
อื่นถ้า (window.attachevent) {
Doscroll ();
-
-
/*Doscroll กำหนดว่า DOM ของ IE6-8 ได้รับการโหลดหรือไม่
-
*@param null
*@Execute Doscroll กำหนดว่า DOM กำลังโหลด
*@caller bindready ()
-
ฟังก์ชั่น doscroll () {
พยายาม{
document.documentelement.doscroll ('ซ้าย');
-
จับ (ข้อผิดพลาด) {
ส่งคืน setTimeout (Doscroll, 20);
-
execfn ();
-
/*คิวเหตุการณ์การดำเนินการ
-
*@param null
*@Execute Loop Execution Event Handler ในคิว
*@caller bindready ()
-
ฟังก์ชั่น execfn () {
ถ้า (! พร้อม) {
พร้อม = จริง;
สำหรับ (var i = 0; i <eventqueue.length; i ++) {
Eventqueue [i]. call (หน้าต่าง);
-
Eventqueue = [];
-
-
// JS ไฟล์ 1
domready (function () {
-
-
// JS File 2
domready (function () {
-
-
// โปรดทราบว่าหากมีการโหลดแบบอะซิงโครนัสอย่าผูกเมธอด DomeRady มิฉะนั้นฟังก์ชั่นจะไม่ถูกเรียกใช้งาน
// เพราะก่อนการดาวน์โหลด js แบบอะซิงโครนัสการดาวน์โหลด domcontentloaded ได้รับการยิงและ addeventListener ไม่สามารถฟังได้เมื่อดำเนินการ
หน้าทดสอบ: มีการโหลดภาพขนาดใหญ่สองภาพ OnLoad ต้องการภาพที่จะโหลดก่อนที่จะสามารถดำเนินการ JS ได้ Domcontentloaded ต้องรอจนกว่า DOM จะถูกโหลดเพื่อเรียกใช้งาน JS คุณสามารถเปิด firebug เพื่อดูกระบวนการโหลด อย่าลืมทำความสะอาดแคชเบราว์เซอร์ก่อนการทดสอบแต่ละครั้ง