Как определить, был ли запущен DOMContentLoaded

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

То, что я хочу, это просто:
Как я могу узнать, что DOMContentLoaded был запущен во время выполнения файла?

Почему это так сложно?
В IE document.readyState показывает интерактивную версию перед DOMContentLoaded.
Я не буду использовать обнаружение браузера никоим образом, это противоречит политике меня и остальных участников.

Какая правильная альтернатива?

Редактировать:

Похоже, я не достаточно ясно. Мне не интересно знать, если событие загрузки уже произошло!!! Я уже знал, как решить эту проблему! Я хочу знать, как решить с DOMContentLoaded!!!

5 ответов

Решение

Чтобы увидеть, все ли ресурсы на странице были загружены:

if (document.readyState === "complete" || document.readyState === "loaded") {
     // document is already ready to go
}

Это давно поддерживается в IE и webkit. Он был добавлен в Firefox в версии 3.6. Вот спецификация. "loaded" для старых браузеров Safari.

Если вы хотите знать, когда страница была загружена и проанализирована, но все подресурсы еще не были загружены (что более похоже на DOMContentLoaded), вы можете добавить "интерактивное" значение:

if (document.readyState === "complete" 
     || document.readyState === "loaded" 
     || document.readyState === "interactive") {
     // document has at least been parsed
}

Кроме того, если вы действительно хотите знать, когда был запущен DOMContentLoaded, вам придется установить для этого обработчик события (до его запуска) и установить флаг при его запуске.

Эта документация MDN также очень хорошо знакома с пониманием состояний DOM.

document.readyState изменяется при запуске этого события. Таким образом, вы можете проверить readyState значение и таким образом сказать, было ли событие сработало или нет. Вот код для запуска start() когда документ готов к этому:

if (/comp|inter|loaded/.test(document.readyState)){
    // In case DOMContentLoaded was already fired, the document readyState will be one of "complete" or "interactive" or (nonstandard) "loaded".
    // The regexp above looks for all three states. A more readable regexp would be /complete|interactive|loaded/
    start();
}else{
    // In case DOMContentLoaded was not yet fired, use it to run the "start" function when document is read for it.
    document.addEventListener('DOMContentLoaded', start, false);
}

Как правильно запустить что-то на DOMContentLoaded (или как можно скорее)

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

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

function runWhenPageIsFullyParsed() {
    // your logic goes here
}

if (document.readyState === "complete") {
    // already fired, so run logic right away
    runWhenPageIsFullyParsed();
} else {
    // not fired yet, so let's listen for the event
    window.addEventListener("DOMContentLoaded", runWhenPageIsFullyParsed);
}

Правильный порядок событий при загрузке страницы:

  • document.readyState изменения к interactive
  • windowс DOMContentLoaded событие запускается
  • document.readyState изменения к complete
  • windowс load событие запускается load

Вы можете проверить полный порядок событий во время загрузки страницы в этой скрипке.

Попробуйте это или посмотрите на эту ссылку

<script>
    function addListener(obj, eventName, listener) { //function to add event
        if (obj.addEventListener) {
            obj.addEventListener(eventName, listener, false);
        } else {
            obj.attachEvent("on" + eventName, listener);
        }
    }

    addListener(document, "DOMContentLoaded", finishedDCL); //add event DOMContentLoaded

    function finishedDCL() {
        alert("Now DOMContentLoaded is complete!");
    }
</script>

Заметка

Если у тебя есть <script> после <link rel="stylesheet" ...>

страница не будет разбираться - и DOMContentLoaded не будет запускаться - пока не будет загружена таблица стилей

Если вы хотите точно знать, был ли запущен DOMContentLoaded, вы можете использовать логический флаг следующим образом:

var loaded=false;
document.addEventListener('DOMContentLoaded',function(){
loaded=true;
...
}

затем проверьте с помощью:

if(loaded) ...

Дело в том, что если какая-то другая библиотека (например, jQuery) уже использовала DOMContentLoaded, вы не сможете использовать ее снова. Это может быть плохой новостью, потому что вы в конечном итоге не сможете ее использовать. Вы скажете, почему бы просто не использовать $(document).ready()потому что, НЕТ!, не все должны использовать jQuery, особенно если это другая библиотека.

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