Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Sự kiện tải trang (Load Events) trong JavaScript

Các sự kiện Load chính

Sự kiệnKích hoạt khiThứ tự
DOMContentLoadedDOM tree xây dựng xong (HTML parse xong), trước CSS/JS/images load1
loadTất cả resource (CSS, JS, images, fonts) đã load xong2
beforeunloadTrước khi rời trang (reload, close, navigate)-
unloadTrang đã 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
    }
});