ฉันต้องการเรียกใช้ javascript ก่อนที่ทั้งหน้าจะโหลด เป็นไปได้หรือไม่ หรือโค้ดเริ่มทำงานบน</html>?
ฉันต้องการเรียกใช้ javascript ก่อนที่ทั้งหน้าจะโหลด เป็นไปได้หรือไม่ หรือโค้ดเริ่มทำงานบน</html>?
คำตอบ:
ไม่เพียง แต่สามารถคุณ แต่คุณต้องให้ความพิเศษที่ไม่ได้ถ้าคุณไม่ต้องการที่จะ :-)
เมื่อเบราว์เซอร์พบscriptแท็กแบบคลาสสิกเมื่อแยกวิเคราะห์ HTML เบราว์เซอร์จะหยุดการแยกวิเคราะห์และส่งต่อไปยังตัวแปล JavaScript ซึ่งเรียกใช้สคริปต์ ตัวแยกวิเคราะห์จะไม่ดำเนินการต่อจนกว่าการเรียกใช้สคริปต์จะเสร็จสมบูรณ์ (เนื่องจากสคริปต์อาจdocument.writeเรียกไปยังมาร์กอัปเอาต์พุตที่ตัวแยกวิเคราะห์ควรจัดการ)
นั่นเป็นลักษณะการทำงานเริ่มต้น แต่คุณมีทางเลือกในการชะลอการเรียกใช้สคริปต์:
ใช้โมดูล JavaScript type="module"สคริปต์รอการตัดบัญชีจนกว่า HTML ได้รับการแยกวิเคราะห์อย่างเต็มที่และ DOM เริ่มต้นสร้าง นี่ไม่ใช่เหตุผลหลักในการใช้โมดูล แต่เป็นสาเหตุหนึ่ง:
<script type="module" src="./my-code.js"></script>
<!-- Or -->
<script type="module">
// Your code here
</script>
โค้ดจะถูกดึงออกมา (ถ้าแยกต่างหาก) และแยกวิเคราะห์พร้อมกับการแยกวิเคราะห์ HTML แต่จะไม่ถูกเรียกใช้จนกว่าการแยกวิเคราะห์ HTML จะเสร็จสิ้น (หากโค้ดโมดูลของคุณเป็นแบบอินไลน์แทนที่จะอยู่ในไฟล์ของตัวเองโค้ดจะถูกเลื่อนออกไปจนกว่าการแยกวิเคราะห์ HTML จะเสร็จสมบูรณ์)
สิ่งนี้ใช้ไม่ได้เมื่อฉันเขียนคำตอบนี้ครั้งแรกในปี 2010 แต่ที่นี่ในปี 2020 เบราว์เซอร์สมัยใหม่หลัก ๆ ทั้งหมดรองรับโมดูลโดยกำเนิดและหากคุณต้องการรองรับเบราว์เซอร์รุ่นเก่าคุณสามารถใช้บันเดิลเลอร์เช่น Webpack และ Rollup.js ได้
ใช้deferแอตทริบิวต์บนแท็กสคริปต์คลาสสิก:
<script defer src="./my-code.js"></script>
เช่นเดียวกับโมดูลโค้ดในmy-code.jsจะถูกดึงและแยกวิเคราะห์ควบคู่ไปกับการแยกวิเคราะห์ HTML แต่จะไม่ถูกเรียกใช้จนกว่าการแยกวิเคราะห์ HTML จะเสร็จสิ้น แต่ , ไม่ได้ทำงานกับเนื้อหาสคริปต์แบบอินไลน์เท่านั้นที่มีไฟล์ภายนอกอ้างอิงทางdefersrc
ฉันไม่คิดว่าเป็นสิ่งที่คุณต้องการ แต่คุณสามารถใช้asyncแอตทริบิวต์เพื่อบอกให้เบราว์เซอร์ดึงโค้ด JavaScript ควบคู่ไปกับการแยกวิเคราะห์ HTML แต่ให้เรียกใช้โดยเร็วที่สุดแม้ว่าการแยกวิเคราะห์ HTML จะไม่สมบูรณ์ . คุณสามารถวางไว้บนtype="module"แท็กหรือใช้แทนแท็กdeferแบบคลาสสิscriptก
วางscriptแท็กไว้ท้ายเอกสารก่อน</body>แท็กปิด:
<!doctype html>
<html>
<!-- ... -->
<body>
<!-- The document's HTML goes here -->
<script type="module" src="./my-code.js"></script><!-- Or inline script -->
</body>
</html>
ด้วยวิธีนี้แม้ว่าโค้ดจะถูกเรียกใช้ทันทีที่พบ แต่องค์ประกอบทั้งหมดที่กำหนดโดย HTML ด้านบนก็มีอยู่และพร้อมที่จะใช้
เคยเป็นเช่นนั้นที่ทำให้เกิดความล่าช้าเพิ่มเติมในบางเบราว์เซอร์เนื่องจากจะไม่เริ่มดึงโค้ดจนกว่าจะscriptพบแท็ก แต่เบราว์เซอร์สมัยใหม่จะสแกนล่วงหน้าและเริ่มดึงข้อมูลล่วงหน้า ถึงกระนั้นนี่ก็เป็นตัวเลือกที่สามในตอนนี้ทั้งโมดูลและdeferเป็นตัวเลือกที่ดีกว่า
ข้อมูลจำเพาะมีแผนภาพประโยชน์แสดงดิบscriptแท็กdefer, async, type="module"และtype="module" asyncและระยะเวลาของเมื่อรหัส JavaScript เป็นความจริงและการทำงาน:
นี่คือตัวอย่างของพฤติกรรมเริ่มต้นscriptแท็กดิบ:
.found {
color: green;
}
<p>Paragraph 1</p>
<script>
if (typeof NodeList !== "undefined" && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = Array.prototype.forEach;
}
document.querySelectorAll("p").forEach(p => {
p.classList.add("found");
});
</script>
<p>Paragraph 2</p>
(ดูคำตอบของฉันที่นี่สำหรับรายละเอียดเกี่ยวกับNodeListรหัสนั้น)
เมื่อคุณเรียกใช้คุณจะเห็น "ย่อหน้าที่ 1" เป็นสีเขียว แต่ "ย่อหน้าที่ 2" เป็นสีดำเนื่องจากสคริปต์ทำงานพร้อมกันกับการแยกวิเคราะห์ HTML ดังนั้นจึงพบเฉพาะย่อหน้าแรกไม่ใช่ย่อหน้าที่สอง
ในทางตรงกันข้ามนี่คือtype="module"สคริปต์:
.found {
color: green;
}
<p>Paragraph 1</p>
<script type="module">
document.querySelectorAll("p").forEach(p => {
p.classList.add("found");
});
</script>
<p>Paragraph 2</p>
สังเกตว่าตอนนี้ทั้งคู่เป็นสีเขียว โค้ดไม่ทำงานจนกว่าการแยกวิเคราะห์ HTML จะเสร็จสมบูรณ์ นอกจากนี้ยังเป็นจริงกับdefer scriptเนื้อหาภายนอก (แต่ไม่ใช่เนื้อหาแบบอินไลน์)
(มีความจำเป็นในการไม่ได้NodeListตรวจสอบเพราะมีเบราว์เซอร์ที่ทันสมัยสนับสนุนโมดูลที่มีอยู่แล้วforEachบนNodeList.)
ในโลกสมัยใหม่นี้ไม่มีค่าที่แท้จริงสำหรับDOMContentLoadedเหตุการณ์ของคุณลักษณะ "พร้อม" ที่ PrototypeJS, jQuery, ExtJS, Dojo และอื่น ๆ ส่วนใหญ่ให้กลับมาในวันนั้น (และยังคงให้) เพียงใช้โมดูลหรือdefer. แม้ย้อนกลับไปในวันนั้นก็ไม่มีเหตุผลในการใช้งานมากนัก (และมักใช้อย่างไม่ถูกต้องถือการนำเสนอหน้าในขณะที่ไลบรารี jQuery ทั้งหมดถูกโหลดเนื่องจากscriptอยู่ในheadแทนที่จะอยู่หลังเอกสาร) นักพัฒนาบางคน Googleตั้งค่าสถานะไว้ก่อน นี่เป็นส่วนหนึ่งของเหตุผลที่แนะนำให้ YUIใส่สคริปต์ไว้ตอนท้ายของวันbodyนี้อีกครั้ง
<body onload="doIt()>"หรือวางไว้ในการทำงานและวางไว้ใน
loadเหตุการณ์เกิดขึ้นช้ามากในรอบการโหลดหน้าเว็บแทบจะไม่เคยเป็นแนวทางปฏิบัติที่ดีที่สุดในการรอให้เรียกใช้ JavaScript จนกว่าจะถึงเวลานั้น แต่ใช่มันเป็นตัวเลือก ฉันได้แก้ไขคำตอบสำหรับปี 2020 แล้ว btw
document.addEventListener('DOMContentLoaded', function(){ //doyour stuff })
คุณสามารถเรียกใช้โค้ดจาวาสคริปต์ได้ตลอดเวลา AFAIK จะดำเนินการในขณะที่เบราว์เซอร์มาถึงแท็ก <script> ที่อยู่ แต่คุณไม่สามารถเข้าถึงองค์ประกอบที่ยังไม่ได้โหลด
ดังนั้นหากคุณต้องการเข้าถึงองค์ประกอบคุณควรรอจนกว่า DOM จะโหลด (ไม่ได้หมายความว่าทั้งหน้าจะโหลดรวมถึงรูปภาพและสิ่งของต่างๆเป็นเพียงโครงสร้างของเอกสารซึ่งโหลดเร็วกว่ามากดังนั้นคุณมักจะชนะ ไม่สังเกตเห็นความล่าช้า) โดยใช้DOMContentLoadedเหตุการณ์หรือฟังก์ชันเช่น$.readyใน jQuery