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

StackOverflow https://stackoverflow.com/questions/65434

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

На данный момент мне известно:

  • DOMContentЗагружено :В Mozilla, Opera 9 и новейших WebKits.Это включает в себя добавление прослушивателя к событию:

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

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

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

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

Для этого 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
});

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

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

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

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

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

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

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()
        }
    }
}

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

setTimeout(MyInitFunction, 0);

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

Плюсом этого является то, что их может быть много, и вам не придется беспокоиться о цепочке событий onLoad.

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

и т. д.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top