Является ли событие DOMContentLoaded ТОЧНО таким же, как функция jQuery.ready()?
Я заменил window.addEventListener('DOMContentLoaded', function() {});
на jQuery $(document).bind('ready', function() {});
, потому что первый из них не работал на IE < 9, и я не хотел играть с .attachEvent()
для этого фиктивного браузера, если бы у меня это было хорошо покрыто самой jQuery.
Вскоре после замены я заметил, что событие DOMContentLoaded
всегда запускалось около 0-2 миллисекунд после загрузки/обновления страницы (по крайней мере, это то, что было зарегистрировано в моем протоколе script), а .ready()
всегда требуется на менее 15-20 миллисекунд, после обновления страницы, для запуска (опять же - как зарегистрировано script).
Я прошу только кормить свое любопытство, почему существует такая "значительная" задержка? Конечно, для меня нет проблем, что jQuery запускает это событие позже. Просто, потому что я хочу знать ВСЕ ответы (и править миром!), Я не могу спать с этим!:]
EDIT: в .ready() function doc некоторый пользователь (Nick (из Nexxar)) указывает, что: "jQuery имитирует не существующее событие" DOMContentLoaded "в IE, но используемый механизм срабатывает намного позже, чем событие, используемое в других браузерах". Может быть, это то же самое, я прошу?
Ответы
Ответ 1
Предполагая браузер, поддерживающий событие:
- Реальное событие может поддерживать любой
document
. jQuery будет использовать только document
, в который он был загружен, независимо от того, что вы передаете ему.
- jQuery будет запускать событие асинхронно, даже если это событие уже произошло. Прикрепление события
'DOMContentLoaded'
ничего не сделает, если событие уже произошло.
В этих браузерах нет задержек, см. http://jsfiddle.net/rqTAX/3/ (занесенные в записях в миллисекундах).
Для браузеров, которые не поддерживают событие, jQuery, очевидно, будет работать и для них. Он будет использовать хакерский механизм, который не совпадает с реальным DOMContentLoaded
и не обязательно будет срабатывать, как только реальный DOMContentLoaded
будет:
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if ( jQuery.isReady ) {
return;
}
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
// and execute any waiting functions
jQuery.ready();
}
Ответ 2
jQuery имитирует это событие, привязывая к событию document
readystatechange
, который является стандартным способом моделирования DOMContentLoaded
в oldIE.
Согласно источнику jQuery, это событие срабатывает "поздно", но до window.onload
. Однако я не могу найти, когда это событие срабатывает точно. DOMContentLoaded
срабатывает, когда DOM построен и готов к написанию сценариев, поэтому readystatechange
срабатывает после этого; возможно, он ждет рендеринга макета или моделирования чего-то подобного, или событие запускается позже в процессе рендеринга/компоновки?
Несмотря на это, он, скорее всего, срабатывает после DOMContentLoaded
, вероятно, из-за того, что IE решит обновить document
readyState
до "complete."
(Если у кого-то есть определенный ответ, опубликуйте комментарий, и я обновлю этот ответ, мне бы хотелось знать, когда именно он срабатывает сам, и я не могу найти этот ответ в любой документации или на любых сайтах я ожидал бы как Quirksmode.)
Ответ 3
Еще одна причина того, что "готов" появится позже (на практике), заключается в том, что к нему может быть подключено много событий. Если какие-либо из них являются длительными синхронными операциями, то готовое событие поступит намного позже. Например, я использую knockout.js, и для инициализации страницы может потребоваться 500 мс.
Однако, используя вашу минимальную тестовую страницу, это, конечно, не так. Я попытался запустить следующее:
console.log(window.performance.timing.domContentLoadedEventEnd -
window.performance.timing.domContentLoadedEventStart);
Это дает около 6 мс даже для вашей простой супер-страницы
Также я взял ваш код и запустил его с помощью инструментов производительности Chrome и обнаружил несколько интересных вещей:
![введите описание изображения здесь]()
- BTW: вертикальная синяя полоса DOMCONTENTLOADED, а зеленая - "первая краска".
- Вы можете видеть, что даже очень простой вызов функции в событии DOMCONTENTLOADED может занимать 5 мс (и это на i7). Помните, что он нуждается в анализе, и что-то нужно инициализировать.
- Обратные вызовы отображаются в голубом цвете (анонимно), первый - из события DOMCONTENTLOADED, а второй - "готовый" обратный вызов.
- Вы увидите "Таймер уволен" (т.е.
setTimeout
). Таким образом, это не мгновенно с помощью каких-либо средств.
Глядя на исходный код jQuery, вы видите, что они фактически устанавливают таймер для обратных вызовов:
// Handle it asynchronously to allow scripts the opportunity to delay ready
window.setTimeout( jQuery.ready );
Я не совсем уверен, что они здесь означают (любая идея), но это объясняет поведение. Я мог видеть, что это полезно для предотвращения условий гонки и блокировки пользовательского интерфейса, но "отсрочка готовности" для меня неясна.