Получение уведомления, когда страница DOM загружена (но до window.onload)

Я знаю, что есть несколько способов получить уведомление, когда тело страницы загружено (до загрузки всех изображений и сторонних ресурсов, что вызывает событие window.onload), но для каждого браузера он разный.

Есть ли окончательный способ сделать это во всех браузерах?

На данный момент я знаю:

  • DOMContentLoaded: в Mozilla, Opera 9 и новейших WebKits. Это включает добавление слушателя к событию:

    document.addEventListener ("DOMContentLoaded", [функция инициализации], ложь);

  • Отложенный сценарий: в IE вы можете создать тег SCRIPT с атрибутом @defer, который будет надежно загружаться только после закрытия тега BODY.

  • Опрос: В других браузерах вы можете продолжать опросы, но есть ли даже стандартная функция для опроса, или вам нужно делать разные вещи в каждом браузере?

Я бы хотел обойтись без использования document.write или внешних файлов.

Это можно сделать просто через jQuery:

$(document).ready(function() { ... })

но я пишу библиотеку JS и не могу рассчитывать на то, что jQuery всегда будет там.

Есть какие-нибудь новости по этому поводу? Этот ответ просидел здесь 2,5 года ... может быть, производители браузеров и стандарты теперь лучше работают?

Akku 12.05.2011 18:08

Нет, хотя IE9 теперь также поддерживает DOMContentLoaded. Так что мы просто сидим и ждем, пока доля рынка браузеров IE9 не опустится ниже 1%.

Justus Romijn 11.03.2013 18:25
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
2
8 665
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Просто возьмите соответствующий фрагмент кода из jQuery, Джон Ресиг охватил большинство основ по этой проблеме уже в jQuery.

Это работает очень хорошо:

setTimeout(MyInitFunction, 0);

Нет, это не так. Это ненадежно по большому счету. Извини. : - /

Már Örlygsson 30.10.2008 05:32
Ответ принят как подходящий

Не существует кроссбраузерного метода для проверки готовности DOM - вот почему существуют такие библиотеки, как jQuery, чтобы абстрагироваться от неприятных мелких кусочков несовместимости.

Mozilla, Opera и современный WebKit поддерживают событие DOMContentLoaded. IE и Safari нуждаются в странных хитростях, таких как прокрутка окна или проверка таблиц стилей. Кровавые подробности содержатся в функции jQuery bindReady().

YUI использует для этого три теста: для Firefox и недавнего WebKit запускается событие DOMContentLoaded. Для более старого Safari document.readyState просматривается, пока он не станет «загруженным» или «завершенным». Для IE создается тег HTML <P> и вызывается метод «doScroll ()», который должен срабатывать, если DOM не готов. Источник для YAHOO.util.Event показывает код, специфичный для YUI. Найдите «doScroll» в Event.js.

Использование такой библиотеки, как jQuery, сэкономит вам бесчисленное количество часов несогласованности браузеров.

В этом случае с jQuery вы можете просто

$(document).ready ( function () {
    //your code here
});

Если вам интересно, вы можете взглянуть на источник, чтобы увидеть, как это делается, но в наши дни я не думаю, что кто-то должен изобретать это колесо, когда автор библиотеки проделал за вас всю болезненную работу.

Я нашел эту страницу, на которой показано компактное автономное решение. Кажется, он работает в каждом браузере и объясняет, как:

http://www.kryogenix.org/days/2007/09/26/shortloaded

Похоже, это получено из этого кода: javascript.nwbox.com/ContentLoaded. Я пробовал этот исходный код во множестве браузеров, и у меня он отлично сработал.

arlomedia 10.04.2012 03:07

Использование setTimeout может работать достаточно хорошо, хотя когда он выполняется, зависит от браузера. Если вы передадите ноль в качестве времени ожидания, браузер выполнит работу, когда все будет «улажено».

Хорошо то, что у вас может быть много из них, и вам не нужно беспокоиться о связывании событий onLoad.

setTimeout(myFunction, 0);
setTimeout(anotherFunction, 0);
setTimeout(function(){ doSomething ...}, 0);

и Т. Д.

Все они будут запущены, когда документ завершит загрузку, или, если вы настроите один после загрузки документа, они будут запускаться после завершения вашего скрипта.

Порядок их выполнения не определен и может меняться в зависимости от браузера. Так что, например, вы не можете рассчитывать на то, что myFunction будет работать раньше, чем anotherFunction.

Все дело в том, чтобы JS выполнялся как можно раньше, но не раньше, чем вся DOM страницы будет на месте - это позволит проверять DOM, не дожидаясь загрузки потенциально медленных изображений.

levik 16.09.2008 18:57

Не гарантируется правильная работа. В этой статье объясняется, почему: snook.ca/archives/javascript/settimeout_solve_domcontentload‌ ed

Morgan Cheng 28.01.2009 14:14

Почему не это:

<body>  
  <!-- various content -->  
  <script type = "text/javascript">  
  <!--  
    myInit();  
  -->
  </script>  
</body>  

Если я правильно понимаю, myInit будет запущен, как только браузер попадет на страницу, что является последним в теле.

К сожалению, это простое решение не работает, если у меня нет контроля над страницей - например, при создании библиотеки JS, которая будет включена через тег <script>.

levik 16.09.2008 18:56

Замечательное кроссбраузерное решение, которое вы ищете… не существует… (представьте себе звук большой толпы, говорящей «ааааа…»).

DomContentLoaded - ваш лучший снимок. Вам все еще нужна техника polling для IE-старых.

  1. Попробуйте использовать addEventListener;
  2. Если недоступен (очевидно, IE), проверьте фреймы;
  3. Если это не кадр, прокрутите до тех пор, пока не перестанет генерироваться ошибка (опрос);
  4. Если кадр, используйте событие IE document.onreadystatechange;
  5. Для других браузеров, не поддерживающих поддержку, используйте старое событие document.onload.

Я нашел следующий пример кода на javascript.info, который вы можете использовать для охвата всех браузеров:

function bindReady(handler){

    var called = false

    function ready() { 
        if (called) return
        called = true
        handler()
    }

    if ( document.addEventListener ) { // native event
        document.addEventListener( "DOMContentLoaded", ready, false )
    } else if ( document.attachEvent ) {  // IE

        try {
            var isFrame = window.frameElement != null
        } catch(e) {}

        // IE, the document is not inside a frame
        if ( document.documentElement.doScroll && !isFrame ) {
            function tryScroll(){
                if (called) return
                try {
                    document.documentElement.doScroll("left")
                    ready()
                } catch(e) {
                    setTimeout(tryScroll, 10)
                }
            }
            tryScroll()
        }

        // IE, the document is inside a frame
        document.attachEvent("onreadystatechange", function(){
            if ( document.readyState === "complete" ) {
                ready()
            }
        })
    }

    // Old browsers
    if (window.addEventListener)
        window.addEventListener('load', ready, false)
    else if (window.attachEvent)
        window.attachEvent('onload', ready)
    else {
        var fn = window.onload // very old browser, copy old onload
        window.onload = function() { // replace by new onload and call the old one
            fn && fn()
            ready()
        }
    }
}

Другие вопросы по теме