Полное руководство: выполнение JavaScript после загрузки страницы
Узнайте, как выполнять JavaScript после загрузки страницы с использованием событий DOMContentLoaded, атрибута defer и события load. Лучшие практики для манипуляции DOM и оптимизации загрузки скриптов.
Как выполнить JavaScript после загрузки страницы?
Я выполняю внешний скрипт с помощью тега <script> внутри раздела <head>. Поскольку скрипт выполняется до полной загрузки страницы, я не могу получить доступ к элементам <body> и другим компонентам DOM. Мне нужно выполнить JavaScript после полной загрузки документа (HTML полностью загружен и разобран в память). Какие события можно отслеживать, которые сработают при завершении загрузки страницы, и как убедиться, что мой JavaScript-код будет выполняться в этот момент?
Для выполнения JavaScript после загрузки страницы следует использовать событие DOMContentLoaded (срабатывает, когда HTML полностью загружен и обработан) или событие load (срабатывает, когда все ресурсы, включая изображения и таблицы стилей, завершили загрузку). Для внешних скриптов в разделе <head> добавление атрибута defer является наиболее современным подходом, так как он загружает скрипты асинхронно, сохраняя порядок выполнения после завершения обработки DOM.
Содержание
- Понимание событий загрузки страницы
- Современные решения для загрузки скриптов
- Подходы на основе событий
- Лучшие практики и рекомендации
- Практические примеры реализации
Понимание событий загрузки страницы
Когда браузер загружает веб-страницу, он проходит через несколько этапов, и время выполнения JavaScript зависит от того, на каком этапе вы хотите перехватить выполнение. Понимание этих событий важно для правильного выполнения кода.
Событие DOMContentLoaded
Событие DOMContentLoaded срабатывает, когда начальный HTML-документ полностью загружен и обработан, без ожидания завершения загрузки таблиц стилей, изображений и фреймов источник. Обычно это момент, когда можно безопасно обращаться к элементам DOM и манипулировать ими.
Основные характеристики DOMContentLoaded:
- Срабатывает после завершения работы HTML-парсера
- Происходит до выполнения отложенных скриптов
- Происходит до выполнения асинхронных скриптов (если они не завершили загрузку)
document.readyStateустанавливается в “interactive” во время этой фазы- Идеально подходит для манипуляций с DOM и базовых взаимодействий
Событие Load
Событие load (на объекте window) срабатывает, когда вся страница загружена, включая все зависимые ресурсы, такие как таблицы стилей, изображения и фреймы источник. Это представляет полное состояние загрузки страницы.
Основные характеристики события load:
- Всегда срабатывает после всех других обработчиков загрузки
- Ожидает завершения загрузки всех внешних ресурсов
document.readyStateустанавливается в “complete” во время этой фазы- Необходимо, когда ваш код зависит от полностью загруженных изображений или полного стиля
Современные решения для загрузки скриптов
Вместо того чтобы полагаться исключительно на обработчики событий, современная веб-разработка предлагает встроенные атрибуты загрузки скриптов, которые могут элегантнее решить вашу проблему.
Атрибут Defer
Атрибут defer, безусловно, является рекомендуемым по умолчанию для большинства сценариев JavaScript. Он предоставляет несколько преимуществ:
- Неблокирующий: Позволяет продолжать обработку HTML во время загрузки скриптов
- Порядковое выполнение: Скрипты выполняются в том порядке, в котором они появляются в документе
- Выполнение при готовности DOM: Скрипты выполняются только после полной обработки DOM
- Улучшение производительности: Скрипты загружаются асинхронно при сохранении порядка выполнения
<script src="your-script.js" defer></script>
Важно: Атрибут
deferигнорируется, если у тега<script>нет атрибута src (т.е. для встроенных скриптов) источник.
Атрибут Async
Атрибут async обеспечивает другое поведение:
- Неблокирующий: Позволяет продолжать обработку HTML во время загрузки скриптов
- Мгновенное выполнение: Скрипты выполняются сразу после загрузки, потенциально прерывая обработку HTML
- Без гарантии порядка: Скрипты выполняются сразу после завершения загрузки
- Случай использования: Идеально подходит для независимых скриптов, таких как аналитика или реклама
<script src="analytics.js" async></script>
Используйте
<script async>, когда скрипт не зависит от чего-либо. Когда скрипт зависит от других скриптов или элементов DOM, используйте<script defer>источник.
Подходы на основе событий
Хотя атрибуты скриптов решают многие случаи, вам все равно понадобятся обработчики событий для более сложных сценариев или при работе с существующими кодовыми базами.
Обработчик события DOMContentLoaded
Это наиболее распространенный подход для обеспечения выполнения вашего кода после готовности DOM:
document.addEventListener('DOMContentLoaded', function() {
// Ваш код здесь - можно безопасно обращаться к элементам DOM
const bodyElements = document.querySelectorAll('body *');
console.log('DOM полностью загружен');
});
Обработчик события Window Load
Для кода, которому абсолютно необходима загрузка всего:
window.addEventListener('load', function() {
// Ваш код здесь - выполняется после загрузки всех ресурсов
const images = document.querySelectorAll('img');
console.log('Все ресурсы, включая изображения, загружены');
});
Событие Readystatechange
Для более детального контроля над процессом загрузки:
document.addEventListener('readystatechange', function() {
if (document.readyState === 'interactive') {
// DOM готов, аналогично DOMContentLoaded
console.log('Документ интерактивен');
} else if (document.readyState === 'complete') {
// Документ и все ресурсы загружены, аналогично событию load
console.log('Документ полностью загружен');
}
});
Лучшие практики и рекомендации
Когда использовать каждый метод
| Сценарий | Рекомендуемый подход | Почему |
|---|---|---|
| Большинство приложений JavaScript | <script defer> |
Неблокирующий, порядковое выполнение, готовность DOM |
| Скрипты аналитики | <script async> |
Независимое выполнение, отсутствие зависимости от порядка |
| Манипуляции с DOM | DOMContentLoaded |
Гарантированная доступность DOM |
| Код, зависящий от изображений | window.onload |
Обеспечивает готовность всех визуальных ресурсов |
| Поддержка старых браузеров | $(document).ready() |
jQuery обеспечивает кросс-браузерную совместимость |
Вопросы производительности
- Всегда размещайте скрипты в head с атрибутом defer, а не в конце body источник
- Defer загружает скрипты в указанном порядке и выполняет их только после загрузки DOM
- Асинхронные скрипты выполняются сразу после загрузки, что может прервать обработку
- Для веб-компонентов рассмотрите возможность не использования async/defer, так как
connectedCallbackсрабатывает при открытии тега источник
Совместимость с браузерами
- Современные браузеры полностью поддерживают атрибуты
deferиasync - Событие
DOMContentLoadedхорошо поддерживается во всех современных браузерах $(document).ready()из jQuery обеспечивает последовательное поведение в старых браузерах
Практические примеры реализации
Современный подход с Defer
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Современная загрузка JavaScript</title>
<!-- Внешние скрипты с defer -->
<script src="https://cdn.example.com/library.js" defer></script>
<script src="your-main-script.js" defer></script>
<!-- Встроенный скрипт не будет использовать defer (игнорируется спецификацией) -->
<script>
// Это выполнится, как только будет встречено
console.log('Встроенный скрипт выполняется немедленно');
</script>
</head>
<body>
<!-- Содержимое страницы здесь -->
<div id="app"></div>
</body>
</html>
Подход с обработчиками событий
// Метод 1: DOMContentLoaded (наиболее распространенный)
document.addEventListener('DOMContentLoaded', function() {
// Можно безопасно обращаться к элементам DOM
const app = document.getElementById('app');
app.textContent = 'DOM готов!';
// Инициализируйте ваше приложение
initializeApp();
});
// Метод 2: Window load (для полной загрузки ресурсов)
window.addEventListener('load', function() {
// Обращение ко всем загруженным ресурсам, включая изображения
const images = document.querySelectorAll('img');
console.log(`Загружено ${images.length} изображений`);
// Инициализация функций, зависящих от изображений
initializeImageGallery();
});
// Метод 3: Readystatechange для большего контроля
document.addEventListener('readystatechange', function() {
if (document.readyState === 'interactive') {
console.log('DOM готов, ресурсы все еще загружаются');
}
if (document.readyState === 'complete') {
console.log('Все полностью загружено');
}
});
// Резервный вариант для старых браузеров (при необходимости)
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', callback);
} else {
callback();
}
function callback() {
// Ваш код, готовый к работе с DOM
}
Совместимость с jQuery
// Подход с jQuery (кросс-браузерный совместимый)
$(document).ready(function() {
// Ваш код здесь
console.log('jQuery: DOM готов');
});
// Или сокращенная версия
$(function() {
console.log('jQuery сокращенная: DOM готов');
});
Источники
- Document: DOMContentLoaded event - Web APIs | MDN
- Window: load event - Web APIs | MDN
- Page: DOMContentLoaded, load, beforeunload, unload - JavaScript.info
- How to Execute JavaScript After Page Load? - GeeksforGeeks
- Scripts: async, defer - JavaScript.info
- Async vs Defer attributes in JavaScript | Most crucial web performance concept
- Async vs Defer in JavaScript Explained - NamasteDev Blogs
- How and when to use Async and Defer attributes | Zell Liew
- Efficiently load JavaScript with defer and async - Flavio Copes
- Script Tag - async & defer - Stack Overflow
Заключение
Чтобы обеспечить выполнение JavaScript после загрузки страницы, у вас есть несколько отличных вариантов в зависимости от ваших конкретных потребностей:
- Используйте
<script defer>в большинстве случаев - этот современный подход обеспечивает неблокирующую загрузку при сохранении порядка выполнения и гарантирует доступность DOM - Слушайте событие
DOMContentLoaded, когда вам нужно добавить обработчики событий в существующий код или выполнить более сложную логику тайминга - Используйте
window.onload, когда ваш код зависит от полностью загруженных ресурсов, таких как изображения или полный стиль - Избегайте встроенных скриптов в head без defer/async, так как они блокируют обработку HTML
Ключевое понимание заключается в том, что defer стал рекомендуемым по умолчанию для большинства сценариев JavaScript, предлагая идеальный баланс производительности и надежности. Он решает именно ту проблему, которую вы описали - позволяет размещать скрипты в <head>, гарантируя их выполнение после готовности DOM, при этом сохраняя правильный порядок выполнения и производительность загрузки.