Другое

Полное руководство: выполнение 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
  • Улучшение производительности: Скрипты загружаются асинхронно при сохранении порядка выполнения
html
<script src="your-script.js" defer></script>

Важно: Атрибут defer игнорируется, если у тега <script> нет атрибута src (т.е. для встроенных скриптов) источник.

Атрибут Async

Атрибут async обеспечивает другое поведение:

  • Неблокирующий: Позволяет продолжать обработку HTML во время загрузки скриптов
  • Мгновенное выполнение: Скрипты выполняются сразу после загрузки, потенциально прерывая обработку HTML
  • Без гарантии порядка: Скрипты выполняются сразу после завершения загрузки
  • Случай использования: Идеально подходит для независимых скриптов, таких как аналитика или реклама
html
<script src="analytics.js" async></script>

Используйте <script async>, когда скрипт не зависит от чего-либо. Когда скрипт зависит от других скриптов или элементов DOM, используйте <script defer> источник.


Подходы на основе событий

Хотя атрибуты скриптов решают многие случаи, вам все равно понадобятся обработчики событий для более сложных сценариев или при работе с существующими кодовыми базами.

Обработчик события DOMContentLoaded

Это наиболее распространенный подход для обеспечения выполнения вашего кода после готовности DOM:

javascript
document.addEventListener('DOMContentLoaded', function() {
    // Ваш код здесь - можно безопасно обращаться к элементам DOM
    const bodyElements = document.querySelectorAll('body *');
    console.log('DOM полностью загружен');
});

Обработчик события Window Load

Для кода, которому абсолютно необходима загрузка всего:

javascript
window.addEventListener('load', function() {
    // Ваш код здесь - выполняется после загрузки всех ресурсов
    const images = document.querySelectorAll('img');
    console.log('Все ресурсы, включая изображения, загружены');
});

Событие Readystatechange

Для более детального контроля над процессом загрузки:

javascript
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

html
<!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>

Подход с обработчиками событий

javascript
// Метод 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

javascript
// Подход с jQuery (кросс-браузерный совместимый)
$(document).ready(function() {
    // Ваш код здесь
    console.log('jQuery: DOM готов');
});

// Или сокращенная версия
$(function() {
    console.log('jQuery сокращенная: DOM готов');
});

Источники

  1. Document: DOMContentLoaded event - Web APIs | MDN
  2. Window: load event - Web APIs | MDN
  3. Page: DOMContentLoaded, load, beforeunload, unload - JavaScript.info
  4. How to Execute JavaScript After Page Load? - GeeksforGeeks
  5. Scripts: async, defer - JavaScript.info
  6. Async vs Defer attributes in JavaScript | Most crucial web performance concept
  7. Async vs Defer in JavaScript Explained - NamasteDev Blogs
  8. How and when to use Async and Defer attributes | Zell Liew
  9. Efficiently load JavaScript with defer and async - Flavio Copes
  10. Script Tag - async & defer - Stack Overflow

Заключение

Чтобы обеспечить выполнение JavaScript после загрузки страницы, у вас есть несколько отличных вариантов в зависимости от ваших конкретных потребностей:

  1. Используйте <script defer> в большинстве случаев - этот современный подход обеспечивает неблокирующую загрузку при сохранении порядка выполнения и гарантирует доступность DOM
  2. Слушайте событие DOMContentLoaded, когда вам нужно добавить обработчики событий в существующий код или выполнить более сложную логику тайминга
  3. Используйте window.onload, когда ваш код зависит от полностью загруженных ресурсов, таких как изображения или полный стиль
  4. Избегайте встроенных скриптов в head без defer/async, так как они блокируют обработку HTML

Ключевое понимание заключается в том, что defer стал рекомендуемым по умолчанию для большинства сценариев JavaScript, предлагая идеальный баланс производительности и надежности. Он решает именно ту проблему, которую вы описали - позволяет размещать скрипты в <head>, гарантируя их выполнение после готовности DOM, при этом сохраняя правильный порядок выполнения и производительность загрузки.

Авторы
Проверено модерацией
Модерация