Để thực thi hàm JavaScript ngay khi trang web tải xong, có các cách sau theo thứ tự khuyến nghị:
Cách 1: DOMContentLoaded Event (Khuyên dùng nhất - Hiện đại)
Chạy khi HTML đã parse xong, DOM sẵn sàng, không chờ CSS/ảnh load xong.
document.addEventListener("DOMContentLoaded", function() {
// Code khởi tạo tại đây
initApp();
loadData();
});
// Hoặc gán function reference
document.addEventListener("DOMContentLoaded", initApp);
function initApp() {
console.log("DOM sẵn sàng!");
}
Cách 2: window.onload (Load Event) - Cũ, chờ toàn bộ tài nguyên
Chạy khi TOÀN BỘ trang (HTML, CSS, JS, Ảnh, Iframe, Font...) đã tải xong. Chậm hơn DOMContentLoaded.
// Cách 1: Gán function reference (Khuyên dùng cho cách này)
window.onload = initApp; // Không dấu ()
// Cách 2: Anonymous function
window.onload = function() {
initApp();
otherInit();
};
// Cách 3: addEventListener (Có thể gán nhiều handler)
window.addEventListener("load", initApp);
window.addEventListener("load", trackAnalytics);
Cách 3: Script ở cuối <body> (Đơn giản, không cần event)
Đặt thẻ <script> ngay trước </body>. Code chạy ngay khi DOM đã sẵn sàng (trước DOMContentLoaded).
<body>
<!-- Nội dung trang -->
<script>
// Chạy ngay lập tức, DOM đã parse xong
initApp();
</script>
</body>
Cách 4: Module Script (ES6+) - Tự động defer
<script type="module">
// Tự động deferred, chạy sau HTML parse, trước DOMContentLoaded
import { initApp } from './app.js';
initApp();
</script>
So sánh
| Cách | Thời điểm chạy | Ưu điểm | Nhược điểm | Khuyên dùng? |
|---|---|---|---|---|
DOMContentLoaded | DOM ready (trước ảnh/CSS) | Nhanh, chuẩn, không chờ tài nguyên nặng | Không chạy nếu script ở head không defer | ✅ CHUẨN |
window.onload | Tất cả tài nguyên xong | Chắc chắn mọi thứ đã load (ảnh, iframe) | Chậm, user chờ lâu thấy hiệu ứng | Chỉ khi cần kích thước ảnh/iframe |
| Script cuối <body> | Ngay sau DOM parse | Đơn giản, không boilerplate, nhanh | Không module, khó quản lý dependency | ✅ Tốt cho script đơn lẻ |
type="module" | Sau parse, trước DOMContentLoaded | ES Module chuẩn, tự động defer, scope riêng | Cần server hỗ trợ CORS/MIME | ✅ Chuẩn hiện đại |
Ví dụ hoàn chỉnh (HTML)
<!DOCTYPE html>
<html>
<head>
<title>Page Load Demo</title>
<script>
// Cách 1: DOMContentLoaded (Khuyên dùng)
document.addEventListener("DOMContentLoaded", function() {
alert('OK - DOMContentLoaded');
});
// Cách 2: window.onload (Chờ ảnh/CSS)
// window.onload = function() { alert('OK - onload'); };
</script>
</head>
<body>
<h1>Trang web</h1>
<img src="large-image.jpg" alt="Ảnh lớn"> <!-- Làm chậm window.onload -->
<!-- Cách 3: Script cuối body -->
<script>
// alert('OK - Script cuối body'); // Chạy trước DOMContentLoaded
</script>
</body>
</html>
Lưu ý quan trọng
- Không gán
window.onload = init()(có dấu ngoặc) -> Gán kết quả trả về (undefined) chứ không gán hàm. - Nếu dùng
window.onloadnhiều lần (gán trực tiếp), lần sau ghi đè lần trước. DùngaddEventListenerđể gán nhiều. - Tránh
<body onload="...">- cũ, lẫn HTML/JS, khó bảo trì. - Trong React/Vue/Angular: Dùng lifecycle hook (
useEffect,mounted) thay vì event load thuần.
Tóm lại: Ưu tiên document.addEventListener("DOMContentLoaded", handler) hoặc đặt script cuối <body>. Dùng window.onload chỉ khi bắt buộc cần kích thước ảnh/iframe. Hiện đại: dùng type="module".