Обработчик загрузки DOM. (DOMContentLoaded)


Содержание

Асинхронные сценарии с обработчиками событий DOMContentLoaded или load не вызываются?

У меня есть script с обработчиком событий DOMContentLoaded —

Я загружаю асинхронно —

Однако обработчик события никогда не вызывается. Если я загружу его синхронно —

Он отлично работает.

(Даже если я изменил событие DOMContentLoaded на событие load , он никогда не вызывал.)

Что дает? Обработчик событий должен регистрироваться независимо от того, как браузер загружается script, нет?

Изменить. Он не работает на бета-версии Chrome 18.0.1025.11, но с DOMContentLoaded он работает на бета-версии Firefox 11 (но с load это не так). Наведите указатель мыши.

ОН БОЛЬШИЕ ЛОРДЫ JAVASCRIPT И ДОМА, МОЛИТЬ ПОКАЗАТЬ ОШИБКУ МОИХ ПУТЕЙ!

Загружая script асинхронно, вы сообщаете браузеру, что он может загрузить этот script независимо от других частей страницы. Это означает, что страница может завершить загрузку и может запустить DOMContentLoaded до загрузки вашего script и до того, как она зарегистрируется для события. Если это произойдет, вы пропустите событие (это уже произошло, когда вы зарегистрировались для него).

В некоторых браузерах вы можете протестировать документ, чтобы узнать, загружена ли она. Я не проверял совместимость браузера, но в Firefox 3.6+ (MDN doc) вы можете проверить:

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

Фактически, как исходный источник и идея реализации, jQuery делает то же самое с этим методом .ready() , и он широко поддерживается. jQuery имеет этот код, когда вызывается .ready() , который сначала проверяет, загружен ли документ. Если это так, он немедленно вызывает готовую функцию, а не привязывает прослушиватель событий:

Page: DOMContentLoaded, load, beforeunload, unload

The lifecycle of an HTML page has three important events:

  • DOMContentLoaded – the browser fully loaded HTML, and the DOM tree is built, but external resources like pictures and stylesheets may be not yet loaded.
  • load – not only HTML is loaded, but also all the external resources: images, styles etc.
  • beforeunload/unload – the user is leaving the page.

Each event may be useful:

  • DOMContentLoaded event – DOM is ready, so the handler can lookup DOM nodes, initialize the interface.
  • load event – external resources are loaded, so styles are applied, image sizes are known etc.
  • beforeunload event – the user is leaving: we can check if the user saved the changes and ask them whether they really want to leave.
  • unload – the user almost left, but we still can initiate some operations, such as sending out statistics.

Let’s explore the details of these events.

DOMContentLoaded

The DOMContentLoaded event happens on the document object.

We must use addEventListener to catch it:

In the example the DOMContentLoaded handler runs when the document is loaded, so it can see all the elements, including below.

But it doesn’t wait for the image to load. So alert shows zero sizes.

At first sight, the DOMContentLoaded event is very simple. The DOM tree is ready – here’s the event. There are few peculiarities though.

DOMContentLoaded and scripts

When the browser processes an HTML-document and comes across a

In the example above, we first see “Library loaded…”, and then “DOM ready!” (all scripts are executed).

There are two exceptions from this rule:

  1. Scripts with the async attribute, that we’ll cover a bit later, don’t block DOMContentLoaded .
  2. Scripts that are generated dynamically with document.createElement(‘script’) and then added to the webpage also don’t block this event.

DOMContentLoaded and styles

External style sheets don’t affect DOM, so DOMContentLoaded does not wait for them.

But there’s a pitfall. If we have a script after the style, then that script must wait until the stylesheet loads:

The reason for this is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above. Naturally, it has to wait for styles to load.

As DOMContentLoaded waits for scripts, it now waits for styles before them as well.

Built-in browser autofill

Firefox, Chrome and Opera autofill forms on DOMContentLoaded .

For instance, if the page has a form with login and password, and the browser remembered the values, then on DOMContentLoaded it may try to autofill them (if approved by the user).

So if DOMContentLoaded is postponed by long-loading scripts, then autofill also awaits. You probably saw that on some sites (if you use browser autofill) – the login/password fields don’t get autofilled immediately, but there’s a delay till the page fully loads. That’s actually the delay until the DOMContentLoaded event.

window.onload

The load event on the window object triggers when the whole page is loaded including styles, images and other resources.

The example below correctly shows image sizes, because window.onload waits for all images:

window.onunload

When a visitor leaves the page, the unload event triggers on window . We can do something there that doesn’t involve a delay, like closing related popup windows.

The notable exception is sending analytics.

Let’s say we gather data about how the page is used: mouse clicks, scrolls, viewed page areas, and so on.

Naturally, unload event is when the user leaves us, and we’d like to save the data on our server.

There exists a special navigator.sendBeacon(url, data) method for such needs, described in the specification https://w3c.github.io/beacon/.

It sends the data in background. The transition to another page is not delayed: the browser leaves the page, but still performs sendBeacon .

Here’s how to use it:

  • The request is sent as POST.
  • We can send not only a string, but also forms and other formats, as described in the chapter Fetch, but usually it’s a stringified object.
  • The data is limited by 64kb.

When the sendBeacon request is finished, the browser probably has already left the document, so there’s no way to get server response (which is usually empty for analytics).

There’s also a keepalive flag for doing such “after-page-left” requests in fetch method for generic network requests. You can find more information in the chapter Fetch API.

If we want to cancel the transition to another page, we can’t do it here. But we can use another event – onbeforeunload .

window.onbeforeunload

If a visitor initiated navigation away from the page or tries to close the window, the beforeunload handler asks for additional confirmation.

If we cancel the event, the browser may ask the visitor if they are sure.

You can try it by running this code and then reloading the page:

For historical reasons, returning a non-empty string also counts as canceling the event. Some time ago browsers used show it as a message, but as the modern specification says, they shouldn’t.

Here’s an example:

The behavior was changed, because some webmasters abused this event handler by showing misleading and annoying messages. So right now old browsers still may show it as a message, but aside of that – there’s no way to customize the message shown to the user.

readyState

What happens if we set the DOMContentLoaded handler after the document is loaded?

Naturally, it never runs.

There are cases when we are not sure whether the document is ready or not. We’d like our function to execute when the DOM is loaded, be it now or later.

The document.readyState property tells us about the current loading state.

There are 3 possible values:

  • «loading» – the document is loading.
  • «interactive» – the document was fully read.
  • «complete» – the document was fully read and all resources (like images) are loaded too.

So we can check document.readyState and setup a handler or execute the code immediately if it’s ready.

There’s also the readystatechange event that triggers when the state changes, so we can print all these states like this:

The readystatechange event is an alternative mechanics of tracking the document loading state, it appeared long ago. Nowadays, it is rarely used.

Let’s see the full events flow for the completeness.

Here’s a document with , and handlers that log events:

The working example is in the sandbox.

The typical output:

  1. [1] initial readyState:loading
  2. [2] readyState:interactive
  3. [2] DOMContentLoaded
  4. [3] iframe onload
  5. [4] img onload
  6. [4] readyState:complete
  7. [4] window onload

The numbers in square brackets denote the approximate time of when it happens. Events labeled with the same digit happen approximately at the same time (± a few ms).

Creative Web Projects

Отложенная загрузка скриптов волнует общественность уже давно, почти 10 лет, — атрибут defer, призванный ее обеспечить, был добавлен в спецификацию еще в прошлом столетии. Однако проблема так и остается актуальной.

Событие window.onload используется программистами для старта их веб-приложения. Это может быть что-то довольно простое, например, выпадающее меню, а может быть и совсем сложное — скажем, запуск почтового приложения. Суть проблемы заключается в том, что событие onload срабатывает только после того, как загрузится вся страница (включая все картинки и другое бинарное содержимое). Если на странице много картинок, то можно заметить значительную задержку между загрузкой страницы и тем моментом, когда она начнет фактически работать. На самом деле, нам нужен только способ определить, когда DOM полностью загрузится, чтобы не ждать еще и загрузку картинок и других элементов оформления.

Firefox впереди планеты всей

В Firefox есть событие специально для этих целей: DOMContentLoaded. Следующий образец кода выполняет как раз то, что нам нужно, в Mozilla-подобных браузерах (а также в Opera 9 и старше):

// для Firefox
if (document.addEventListener) <
document.addEventListener(«DOMContentLoaded», init, false);
>

А Internet Explorer?

IE поддерживает замечательный атрибут для тега

Содержание этого внешнего скрипта будет состоять только из одной строчки кода:

Условные комментарии

Есть некоторая проблема с этим подходом. Другие браузеры проигнорируют атрибут defer и загрузят этот скрипт сразу же. Существует несколько способов, как можно с этим побороться. Можно воспользоваться условными комментариями, чтобы скрыть «отложенный» скрипт:

IE также поддерживает условную компиляцию. Следующий код будет JavaScript- эквивалентом для заявленного выше HTML-кода:

// для Internet Explorer
/*@cc_on @*/
/*@if (@_win32)
document.write(«

Сэкономьте время и деньги при помощи CSS

ля контроля над оформлением текста используйте CSS — Cascading Style Sheets (каскадные таблицы стилей). Это не только уменьшит расходы на хранение и трафик при эксплуатации сайта, но и упростит поддержку сайта, а также воз­можную и неизбежную его переделку. CSS обеспечивают общий способ управления компоновкой и дизайном Web-документов. Более подробно мы рассмотрим CSS в главе 7, […]

Высокочастотные, низкочастотные и среднечастотные запросы

munix: Кто скажет какая между ними разница. В принципе я понимаю, но в циферках хотелось бы. Сколько должно быть запросов в месяц (день) что бы этот запрос был высокочастотным? И так далее… overnight: На эту тему вечные споры. НЧ, это то, что можно продвинуть хорошо оптимизированной страницей или 1-2 ссылками, но бывают ещё НК, СК […]

Оптимизатор — друг или враг пользователя?

Существует мнение, что поисковая оптимизация — это всегда обман поисковика и, следовательно, человека, ищущего информацию в сети. Действительно, многие из существующих и работающих методов оптимизации сегодня позволяют вывести сайт на неплохие позиции практически без использования информативного, интересного пользователю контента. Оптимизатор, таким образом, выступает в роли врага нормального человека, собиравшегося поискать в сети информацию о новой […]

Evgeniy Kutischev

About front end development

7 января 2011 г.

Кроссбраузерный DOMContentLoaded

Многие из вас наверняка знают про событие DOMContentLoaded. Вкратце — это событие позволяет запускать выполнение кода сразу после того, как будет готово DOM-дерево. Это отличная альтернатива событию onload, которое срабатывает только после того, как будет загружен весь документ, включая все внешние файлы и изображения. О преимуществах DOMContentLoaded более детально говорить, я думаю, не стоит. Но к сожалению свободно пользоваться DOMContentLoaded на данный момент нельзя, в виду того, что не все браузеры это событие поддерживают. А не поддерживают это событие вот какие браузеры:

  • Internet Explorer до 9-ой версии
  • Opera до 9-ой версии
  • Gecko-based браузеры с версией движка ниже 1.8
    • Firefox ниже версии 1.5

  • Webkit-based браузеры с версией движка ниже 525.13
    • Safari ниже версии 3.1

Данные о поддержке браузерами события DOMContentLoaded взяты из скрипта contentloaded.js достопочтенного Diego Perini.

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

Самые, пожалуй, популярные методы запуска кода по завершении построения DOM-дерева — это использование JavaScript-фреймворков. В jQuery это делается вот так:

В MooTools это выглядит так:

Но иногда подключать целую библиотеку только ради DOMContentLoaded — это через чур. Тогда я решил поискать готовые решения эмуляции этого события.

Вначале я наткнулся на уже упомянутый выше скрипт от Diego Perini ContentLoaded. Скрипт основывается на определении браузера и, в зависимости от того какой браузер использует клиент, мы используем тот или иной метод для скорейшего запуска обработчика после того, как готово DOM-дерево.

Для Safari версий ниже 3.1 скрипт проверяет свойство document.readyState. Если значение этого свойства равно complete или loaded , то запускается обработчик события, в противном случае проверка выполняется повторно через 10 милисекунд.

В IE для проверки загруженности DOM-дерева используется проприетарная функция doScroll(), которая выкинет ошибку, если попытаться запустить её до того, как будет построено DOM-дерево. doScroll()вызывается до тех пор, пока не перестанет выдавать ошибку и тогда запускается необходимый код.

Для браузеров, которые не поддерживают DOMContentLoaded и не являются Internet Explorer’ом, обработчик вешается на событие onload.

Помимо решения от Diego Perini, я наткрнулся на статью «Кроссбраузерное событие onDOMContentLoaded».

Короче, решение от Diego Perini, на мой взгляд, не самое лучшее. Есть более толковый способ и он подробно расписан в статье «Кроссбраузерное событие onDOMContentLoaded».

Обработчик загрузки DOM. (DOMContentLoaded)

Для начала определимся с самой проблемой. Событие window.onload используется программистами для старта их веб-приложения. Это может быть что-то довольно простое, например, выпадающее меню, а может быть и совсем сложное, как пример, запуск почтового приложения. Суть проблемы заключается в том, что событие onload срабатывает только после того, как загрузится вся страница (включая все картинки и другое бинарное содержимое). Если на странице много картинок, то можно заметить некоторую задержку между загрузкой страницы и тем моментом, когда она начнет фактически работать. На самом деле, нам нужно только узнать способ определить, когда DOM полностью загрузится, а не ждать еще и загрузку картинок.

Mozilla впереди планеты всей

У Mozilla (прим.: на данный момент Firefox является более актуальным, поэтому далее упоминается именно он) есть (недокументированное) событие специально для этих целей: DOMContentLoaded . Следующий образец кода выполняет как раз то, что нам нужно в Mozilla-подобных браузерах (а также в Opera 9):

А Internet Explorer?

Содержание этого внешнего скрипта будет состоять только из одной строчки кода:

Условные комментарии

Есть некоторая проблема с этим подходом. Другие браузеры проигнорируют атрибут defer и загрузят этот скрипт сразу же. Существует несколько способов, как можно с этим побороться. Моим любимым методом является использование условных комментариев (conditional comments), чтобы скрыть «отложенный» скрипт:

IE также поддерживает условную компиляцию (conditional compilation). Следующий код будет JavaScript-эквивалентом для заявленного выше HTML-кода:

Обработчик загрузки DOM. (DOMContentLoaded)

16187 просмотра

4 ответа

153 Репутация автора

У меня есть скрипт с DOMContentLoaded обработчиком событий

Который я загружаю асинхронно

Однако обработчик события никогда не вызывается . Если я загружу это синхронно

(Даже если я изменю DOMContentLoaded событие на load событие, оно никогда не вызывается.)

Что дает? Обработчик события должен быть зарегистрирован независимо от того, как скрипт загружается браузером, нет?

Изменить : Это не работает на бета-версии Chrome 18.0.1025.11, но, с DOMContentLoaded , это работает на бета-версии Firefox 11 (но с load этим не работает). Пойди разберись.

О, БОЛЬШОЕ БОЛЬШОЕ JAVASCRIPT И DOM, МОЛИТВА ПОКАЗАТЬ ОШИБКУ МОИХ ПУТЕЙ!

Ответы (4)

55 плюса

452711 Репутация автора

Загружая скрипт асинхронно, вы сообщаете браузеру, что он может загрузить этот скрипт независимо от других частей страницы. Это означает, что страница может закончить загрузку и может DOMContentLoaded сработать ДО того, как загрузится ваш скрипт и до того, как он зарегистрируется для события. Если это произойдет, вы пропустите событие (это уже произошло, когда вы зарегистрировались для него).

В некоторых браузерах вы можете проверить документ, чтобы увидеть, загружен ли он уже. Я не проверил всю совместимость браузера, но в Firefox 3.6+ ( MDN doc ) вы можете проверить:

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

Фактически, в качестве справочного источника и идеи реализации, jQuery делает то же самое со своим .ready() методом, и это выглядит широко поддерживаемым. jQuery имеет этот код при .ready() вызове, который сначала проверяет, загружен ли уже документ. Если это так, он немедленно вызывает функцию ready, а не привязывает прослушиватель событий:

23 плюса

371 Репутация автора

Это не окончательный ответ, но я понял, почему некорректно использовать async со сценарием, который должен изменить DOM, поэтому необходимо дождаться события DOMContentLoaded. Надежда может быть полезной.

3 плюса

394 Репутация автора

Одним из способов решения этой проблемы является использование события load для объекта window.

Это произойдет позже, чем DOMContentLoaded, но, по крайней мере, вам не нужно беспокоиться об отсутствии события.

Если вам действительно нужно перехватить событие DOMContentLoaded, вы можете использовать объект Promise. Обещание будет выполнено, даже если это произошло раньше:

3 плюса

198 Репутация автора

Большинство ванильных функций JS Ready НЕ учитывают сценарий, когда DOMContentLoaded обработчик запускается после того, как документ уже загружен. Это означает, что функция никогда не будет работать . Это может произойти , если вы используете DOMContentLoaded в качестве async внешнего скрипта ( ).

Код ниже проверяет DOMContentLoaded только, если документ еще readyState не interactive или complete .

Асинхронно загруженные скрипты с обработчиками событий DOMContentLoaded или load не вызываются?

у меня есть скрипт DOMContentLoaded обработчик-


который я загружаю асинхронно —

однако обработчик событий это не называется. Если я загружаю его синхронно —

он работает нормально.

(даже если я изменю DOMContentLoaded событие load событие, оно никогда не вызывается.)

что это дает? Обработчик события должен быть зарегистрирован независимо от того, как скрипт загружен браузер, нет?

редактировать: он не работает на Chrome 18.0.1025.11 beta, но с DOMContentLoaded , это тут в бета-версии Firefox 11 (но с load это не так). Иди разберись.

О ВЕЛИКИЕ ВЛАДЫКИ JAVASCRIPT И DOM, ПОЖАЛУЙСТА, ПОКАЖИТЕ ОШИБКУ МОИХ ПУТЕЙ!

4 ответов

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

в некоторых браузерах, вы можете проверить, чтобы увидеть, если он уже загружен. Я не проверил все совместимость браузера, но в Firefox 3.6+ (MDN doc), вы можете увидеть:

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

на самом деле, как ссылочный источник и идея реализации, jQuery делает то же самое с ним .ready() метод и он выглядит широко поддерживается. jQuery имеет этот код после .ready() — Это называется, что сначала проверяет, если документ уже нагруженный. Если это так, он немедленно вызывает функцию ready, а не привязывает прослушиватель событий:

Это не окончательный ответ, но заставил меня понять, почему неправильно использовать async со скриптом, который нужно изменить DOM, поэтому нужно дождаться события DOMContentLoaded. Надежда может быть полезной.

один из способов обойти это-использовать событие load для объекта window.

это произойдет позже, чем DOMContentLoaded, но, по крайней мере, вам не придется беспокоиться о пропущенном событии.

Если вам действительно нужно поймать событие DOMContentLoaded, вы можете использовать объект Promise. Обещание разрешится, даже если это произошло раньше:

имитация медленного подключения 3G используя Chrome devtools у меня были проблемы с манипулированием DOM из внешнего async сценарий, однако этот фрагмент, который я нашел где-то на GitHub решил это за меня:

может ли кто-нибудь поручиться за это?
как это соотносится с уже предложенных решений?

Обработчик загрузки DOM. (DOMContentLoaded)

Загрузка документа: DOMContentLoaded, load, beforeunload, unload

Процесс загрузки HTML-документа, условно, состоит из трёх стадий:

  • DOMContentLoaded — браузер полностью загрузил HTML и построил DOM-дерево.
  • load — браузер загрузил все ресурсы.
  • beforeunload/unload — уход со страницы.

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

  • DOMContentLoaded — означает, что все DOM-элементы разметки уже созданы, можно их искать, вешать обработчики, создавать интерфейс, но при этом, возможно, ещё не догрузились какие-то картинки или стили.
  • load — страница и все ресурсы загружены, используется редко, обычно нет нужды ждать этого момента.
  • beforeunload/unload — можно проверить, сохранил ли посетитель изменения, уточнить, действительно ли он хочет покинуть страницу.

Далее мы рассмотрим важные детали этих событий.

Событие DOMContentLoaded происходит на document и поддерживается во всех браузерах, кроме IE8-. Про поддержку аналогичного функционала в старых IE мы поговорим в конце главы.

Обработчик на него вешается только через addEventListener :

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

Поэтому на момент вывода alert и сама картинка будет невидна и её размеры — неизвестны (кроме случая, когда картинка взята из кеша браузера).

В своей сути, событие onDOMContentLoaded — простое, как пробка. Полностью создано DOM-дерево — и вот событие. Но с ним связан ряд существенных тонкостей.

DOMContentLoaded и скрипты

Если в документе есть теги , то браузер обязан их выполнить до того, как построит DOM. Поэтому событие DOMContentLoaded ждёт загрузки и выполнения таких скриптов.

Исключением являются скрипты с атрибутами async и defer , которые подгружаются асинхронно.

Побочный эффект: если на странице подключается скрипт с внешнего ресурса (к примеру, реклама), и он тормозит, то событие DOMContentLoaded и связанные с ним действия могут сильно задержаться.

Современные системы рекламы используют атрибут async , либо вставляют скрипты через DOM: document.createElement(‘script’). , что работает так же как async : такой скрипт выполняется полностью независимо от страницы и от других скриптов — сам ничего не ждёт и ничего не блокирует.

DOMContentLoaded и стили

Внешние стили никак не влияют на событие DOMContentLoaded . Но есть один нюанс.

Если после стиля идёт скрипт, то этот скрипт обязан дождаться, пока стиль загрузится:

Такое поведение прописано в стандарте. Его причина — скрипт может захотеть получить информацию со страницы, зависящую от стилей, например, ширину элемента, и поэтому обязан дождаться загрузки style.css .

Побочный эффект — так как событие DOMContentLoaded будет ждать выполнения скрипта, то оно подождёт и загрузки стилей, которые идут перед .

Firefox/Chrome/Opera автозаполняют формы по DOMContentLoaded .

Это означает, что если на странице есть форма для ввода логина-пароля, то браузер введёт в неё запомненные значения только по DOMContentLoaded .

Побочный эффект: если DOMContentLoaded ожидает множества скриптов и стилей, то автозаполнение не сработает до полной их загрузки.

Конечно, это довод в пользу того, чтобы не задерживать DOMContentLoaded , в частности — использовать у скриптов атрибуты async и defer .

Событие onload на window срабатывает, когда загружается вся страница, включая ресурсы на ней — стили, картинки, ифреймы и т.п.

Пример ниже выведет alert лишь после полной загрузки окна, включая IFRAME и картинку:

Когда человек уходит со страницы или закрывает окно, на window срабатывает событие unload . В нём можно сделать что-то, не требующее ожидания, например, закрыть вспомогательные popup-окна, но отменить сам переход нельзя.

Это позволяет другое событие — onbeforeunload , которое поэтому используется гораздо чаще.

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

Для этого ему нужно вернуть строку. По историческим причинам некоторые браузеры покажут ее, но большинство – стандартное сообщение.

Эмуляция DOMContentLoaded для IE8-

Прежде чем что-то эмулировать, заметим, что альтернативой событию onDOMContentLoaded является вызов функции init из скрипта в самом конце BODY , когда основная часть DOM уже готова:

Причина, по которой обычно предпочитают именно событие — одна: удобство. Вешается обработчик и не надо ничего писать в конец BODY .

Если вы всё же хотите использовать onDOMContentLoaded кросс-браузерно, то нужно либо подключить какой-нибудь фреймворк — почти все предоставляют такой функционал, либо использовать функцию из мини-библиотеки jquery.documentReady.js.


Несмотря на то, что в названии содержится слово «jquery», эта библиотечка не требует jQuery. Наоборот, она представляет собой единственную функцию с названием $ , вызов которой $(callback) добавляет обработчик callback на DOMContentLoaded (можно вызывать много раз), либо, если документ уже загружен — выполняет его тут же.

Здесь alert сработает до загрузки картинки, но после создания DOM, в частности, после появления текста. И так будет для всех браузеров, включая даже очень старые IE.

««smart header=»Как именно эмулируется DOMContentLoaded ?» Технически, эмуляция `DOMContentLoaded` для старых IE осуществляется очень забавно.

Основной приём — это попытка прокрутить документ вызовом:

Метод doScroll работает только в IE и «методом тыка» было обнаружено, что он бросает исключение, если DOM не полностью создан.

Поэтому библиотека пытается вызвать прокрутку, если не получается — через setTimeout(. 1) пытается прокрутить его ещё раз, и так до тех пор, пока действие не перестанет вызывать ошибку. На этом этапе документ считается загрузившимся.

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

Реализация и альтернатива основных JQuery функций на чистом JavaScript

Когда я начинал учить веб-программирование, встретил лучший из всех, по моему мнению, фреймворков — JQuery. В то далёкое время нельзя было представить нормальное программирование без него, так как он мог делать одной строкой то, что делал JavaScript за 95.

В сегодняшнее время, JavaScript очень изменился. В него добавили большой функционал, который сокращает количество кода в разы и делает программирование более удобным. Но даже с этими обновлениями он не может воспроизвести некоторые, даже самые простые, функции из JQuery, и когда мы решаем отказаться от этого фремворка, то чувствует некую трудность из за этого.

Так вот, в этой статье я хочу рассказать о реализациях некоторых функций из JQuery на чистом JavaScript.

$(document).ready( Function ); или $( Function );

Для тех кто не знает, это функция готовности DOM дерева. Т.е. эта функция запускается, когда DOM страницы был полностью загружен.

Начиная с IE9+ эту функцию можно заменить с помощью события DOMContentLoaded повешенного на document .

Если вам нужна поддержка начиная с IE4+, то можно воспользоваться более старым методом — с помощью события readystatechange повешенного на document и проверкой readyState .

Если же мы посмотрим в исходники JQuery, то выйдет следующая функция:

Запуск функции происходить таким образом:

$.ajax( Object );

Для тех кто не знает, эта функция выполняет асинхронный HTTP (Ajax) запрос.

Как бы это ни было банально, но альтернативой для Jquery.ajax() является XMLHttpRequest

Немного об использовании:

Для начала, нам бы следовало создать кроссбраузерную функцию для отправки, т.к. в разных браузерах функция отправки может быть разной. Она создаётся таким образом:

А вот сам пример стандартного POST запроса с обработкой ошибок:

По такой же технологией сделана функция JQuery AJAX.

Глобальная функция $(. );

Если кто не знает, этой функцией создаётся глобальный JQuery объект.

Тут я не буду расписывать полный функционал этой функции, так как это займёт у меня минимум неделю, а просто напишу, как создаётся подобная вещь по примеру JQuery.

Для начала создадим обычную функцию, к примеру, Library с аргументами (селектор и контекст).

Далее пишем общую функцию. В JQuery значения, которые попадают в функцию перебираются с помощью условий и выводится результат

Теперь мы можем добавить запуск этой функции через основную

Обработчик загрузки DOM. (DOMContentLoaded)

16187 просмотра

4 ответа

153 Репутация автора

У меня есть скрипт с DOMContentLoaded обработчиком событий

Который я загружаю асинхронно

Однако обработчик события никогда не вызывается . Если я загружу это синхронно

(Даже если я изменю DOMContentLoaded событие на load событие, оно никогда не вызывается.)

Что дает? Обработчик события должен быть зарегистрирован независимо от того, как скрипт загружается браузером, нет?

Изменить : Это не работает на бета-версии Chrome 18.0.1025.11, но, с DOMContentLoaded , это работает на бета-версии Firefox 11 (но с load этим не работает). Пойди разберись.

О, БОЛЬШОЕ БОЛЬШОЕ JAVASCRIPT И DOM, МОЛИТВА ПОКАЗАТЬ ОШИБКУ МОИХ ПУТЕЙ!

Ответы (4)

55 плюса

452711 Репутация автора

Загружая скрипт асинхронно, вы сообщаете браузеру, что он может загрузить этот скрипт независимо от других частей страницы. Это означает, что страница может закончить загрузку и может DOMContentLoaded сработать ДО того, как загрузится ваш скрипт и до того, как он зарегистрируется для события. Если это произойдет, вы пропустите событие (это уже произошло, когда вы зарегистрировались для него).

В некоторых браузерах вы можете проверить документ, чтобы увидеть, загружен ли он уже. Я не проверил всю совместимость браузера, но в Firefox 3.6+ ( MDN doc ) вы можете проверить:

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

Фактически, в качестве справочного источника и идеи реализации, jQuery делает то же самое со своим .ready() методом, и это выглядит широко поддерживаемым. jQuery имеет этот код при .ready() вызове, который сначала проверяет, загружен ли уже документ. Если это так, он немедленно вызывает функцию ready, а не привязывает прослушиватель событий:

23 плюса

371 Репутация автора

Это не окончательный ответ, но я понял, почему некорректно использовать async со сценарием, который должен изменить DOM, поэтому необходимо дождаться события DOMContentLoaded. Надежда может быть полезной.

3 плюса

394 Репутация автора

Одним из способов решения этой проблемы является использование события load для объекта window.

Это произойдет позже, чем DOMContentLoaded, но, по крайней мере, вам не нужно беспокоиться об отсутствии события.

Если вам действительно нужно перехватить событие DOMContentLoaded, вы можете использовать объект Promise. Обещание будет выполнено, даже если это произошло раньше:

3 плюса

198 Репутация автора

Большинство ванильных функций JS Ready НЕ учитывают сценарий, когда DOMContentLoaded обработчик запускается после того, как документ уже загружен. Это означает, что функция никогда не будет работать . Это может произойти , если вы используете DOMContentLoaded в качестве async внешнего скрипта ( ).

Код ниже проверяет DOMContentLoaded только, если документ еще readyState не interactive или complete .

Илон Маск рекомендует:  TRect - Тип Delphi
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL