Load Events ควบคุมจุดเวลาต่างๆ ของการโหลดหน้าเว็บ มี 4 เหตุการณ์หลัก ที่เกิดขึ้นตามลำดับ
ลำดับเหตุการณ์โหลดหน้า
- DOMContentLoaded - DOM Tree สร้างเสร็จ (HTML Parse เสร็จ) แต่ External Resources (CSS, Images, Fonts) ยังโหลดไม่เสร็จ
- load - ทุกอย่างโหลดเสร็จแล้ว (HTML, CSS, JS, Images, Fonts, Iframes)
- beforeunload - ก่อนหน้าจะ Unload (ปิดแท็บ, Refresh, Navigate ไปหน้าอื่น) - สามารถยกเลิกได้
- unload - หน้า Unload เสร็จแล้ว - ไม่สามารถยกเลิกได้
ตัวอย่าง: ตรวจจับ DOMContentLoaded
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Load Events</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; padding: 20px; }
.result { font-size: 18px; font-weight: 500; color: blueviolet; }
.event-log { background: #f8f9fa; padding: 10px; margin: 5px 0; border-left: 3px solid #667eea; font-family: monospace; }
</style>
</head>
<body>
<h1>Load Events ใน JavaScript</h1>
<div class="result" id="log"></div>
<script>
const log = document.getElementById("log");
function addLog(eventName, details = "") {
const time = new Date().toLocaleTimeString("th-TH", { hour12: false });
log.innerHTML += `[${time}] ${eventName} ${details}`;
}
// 1. DOMContentLoaded - เร็วที่สุด
document.addEventListener("DOMContentLoaded", () => {
addLog("DOMContentLoaded", "- DOM พร้อม จัดการ Element ได้แล้ว");
initApp(); // เริ่มต้นแอปได้ที่นี่
});
// 2. Load - ช้าที่สุด (รอทุกอย่าง)
window.addEventListener("load", () => {
addLog("load", "- ทุก Resource โหลดเสร็จ (Images, CSS, Fonts)");
});
// 3. Beforeunload - ก่อนปิดหน้า
window.addEventListener("beforeunload", (e) => {
// ถ้ามีข้อมูลไม่ได้บันทึก ให้เตือน
if (hasUnsavedChanges()) {
e.preventDefault();
e.returnValue = ""; // Chrome ต้องการค่านี้
return ""; // Legacy browsers
}
});
// 4. Unload - ปิดหน้าแล้ว (ไม่สามารถยกเลิกได้)
window.addEventListener("unload", () => {
// ทำ Cleanup เร็วๆ เช่น send analytics beacon
navigator.sendBeacon("/analytics/leave", JSON.stringify({ page: location.pathname }));
// ไม่ควรทำ Async operations ที่นี่ (อาจไม่สำเร็จ)
});
function initApp() {
addLog("App Init", "- เริ่มต้นแอปพลิเคชัน");
}
function hasUnsavedChanges() {
// ตัวอย่าง: ตรวจสอบ Form Dirty
return document.querySelector("form")?.classList.contains("dirty") || false;
}
</script>
</body>
</html>
ผลลัพธ์ (ลำดับใน Console)
[10:30:15] DOMContentLoaded - DOM พร้อม จัดการ Element ได้แล้ว
[10:30:15] App Init - เริ่มต้นแอปพลิเคชัน
[10:30:16] load - ทุก Resource โหลดเสร็จ (Images, CSS, Fonts)
... (เวลาผ่านไป ผู้ใช้ปิดแท็บ)
[10:35:22] beforeunload - กำลังจะปิดหน้า
[10:35:22] unload - หน้าถูก Unload แล้ว
ความแตกต่างสำคัญ: DOMContentLoaded vs Load
| เหตุการณ์ | เวลา | เหมาะสำหรับ |
|---|---|---|
| DOMContentLoaded | เร็ว (~100-300ms) | เริ่มต้น App, Query DOM, Bind Events |
| load | ช้า (~1-5s+) | วัดขนาดรูปภาพ, Layout ที่ต้องรอ CSS/Fonts |
Best Practices
- ✅ ใช้ DOMContentLoaded สำหรับ Initialization หลัก (เร็วกว่า)
- ✅ ใช้ load เฉพาะต้องการขนาดรูปภาพหรือ Layout ที่พึ่งพา External Resources
- ✅ ใช้ beforeunload เฉพาะต้องเตือน Unsaved Changes (อย่าลงทะเบียนถ้าไม่จำเป็น - ทำให้ช้า)
- ✅ ใช้ navigator.sendBeacon() ใน unload สำหรับ Analytics (น่าเชื่อถือกว่า XHR/Fetch)
- ❌ อย่าทำ Heavy Work ใน Load Events (Blocking)
Script Loading และ Load Events
<!-- Normal: Blocking HTML Parsing -->
<script src="app.js"></script>
<!-- Defer: รอ DOMContentLoaded (แนะนำสำหรับ Module/App) -->
<script src="app.js" defer></script>
<!-- Async: โหลดขนานกัน Execute ทันทีโหลดเสร็จ (ไม่รับประกันลำดับ) -->
<script src="analytics.js" async></script>
<!-- Module: Defer โดยอัตโนมัติ -->
<script type="module" src="app.js"></script>