Các sự kiện Load chính
| Sự kiện | Kích hoạt khi | Thứ tự |
|---|---|---|
| DOMContentLoaded | DOM tree xây dựng xong (HTML parse xong), trước CSS/JS/images load | 1 |
| load | Tất cả resource (CSS, JS, images, fonts) đã load xong | 2 |
| beforeunload | Trước khi rời trang (reload, close, navigate) | - |
| unload | Trang đã unload hoàn toàn | - |
Thứ tự thực thi
1. HTML parse → DOM tree ready 2. DOMContentLoaded.fire() 3. CSS/JS/Images load (parallel) 4. load.fire() --- User rời trang: 5. beforeunload.fire() (có thể cancel) 6. unload.fire()
Ví dụ: DOMContentLoaded
<!DOCTYPE html>
<html lang="vi">
<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', sans-serif; padding: 20px; }
.result { font-size: 16px; font-weight: 500; color: #6a1b9a; margin: 20px 0; padding: 15px; background: #f3e5f5; border-radius: 4px; white-space: pre-wrap; }
</style>
</head>
<body>
<h1>Load Events trong JavaScript</h1>
<div class="result" id="result"></div>
<img src="https://picsum.photos/400/200" alt="Test image" style="max-width:100%">
<script>
const resEle = document.getElementById('result');
const logs = [];
function log(msg) {
logs.push(`[${new Date().toLocaleTimeString()}] ${msg}`);
resEle.textContent = logs.join('\n');
}
// 1. DOMContentLoaded - Sớm nhất có thể thao tác DOM
document.addEventListener('DOMContentLoaded', () => {
log('✅ DOMContentLoaded: DOM sẵn sàng, có thể thao tác element');
});
// 2. load - Tất cả resource xong
window.addEventListener('load', () => {
log('🌐 load: Tất cả resource (CSS, JS, images) đã load xong');
});
// 3. beforeunload - Cảnh báo trước khi rời
window.addEventListener('beforeunload', (e) => {
const message = 'Bạn có thay đổi chưa lưu. Chắc chắn muốn rời?';
e.preventDefault();
e.returnValue = message; // Chrome/Firefox cần này
return message;
});
// 4. unload - Dọn dẹp (gửi analytics, close connections)
window.addEventListener('unload', () => {
// Chỉ dùng cho gửi beacon (navigator.sendBeacon)
navigator.sendBeacon('/analytics/unload', JSON.stringify({ time: Date.now() }));
// Không thể chạy async code, alert, confirm ở đây
});
</script>
</body>
</html>
Kết quả
Console log theo thứ tự:
1. DOMContentLoaded (DOM ready)
2. load (sau khi ảnh load xong)
Best Practices
DOMContentLoaded - Dùng cho:
- Khởi tạo UI components
- Gắn event listeners
- Query DOM elements
- Bắt đầu app logic
load - Dùng cho:
- Lấy kích thước ảnh (
img.naturalWidth) - Khởi tạo thư viện cần CSS layout xong
- Preload resources cho trang tiếp theo
beforeunload - Lưu ý:
- Chỉ hiển thị confirm nếu user đã interact với trang
- Không tùy chỉnh được message trên Chrome/Firefox hiện đại
- Dùng
e.preventDefault()+e.returnValue
unload - Lưu ý:
- Không chạy async/await, fetch, setTimeout
- Chỉ dùng
navigator.sendBeacon()cho analytics - Tránh dùng unload, ưu tiên
pagehide(bfcache friendly)
Modern Alternative: pagehide / pageshow
// Tốt hơn unload - tương thích bfcache (back-forward cache)
window.addEventListener('pagehide', (e) => {
if (e.persisted) {
// Trang được cache, có thể restore nhanh
console.log('Page cached');
} else {
// Page unload thật sự
console.log('Page unloaded');
}
});
window.addEventListener('pageshow', (e) => {
if (e.persisted) {
console.log('Page restored from bfcache');
// Refresh data nếu cần
}
});