Javascript перед загрузкой страницы

Document: DOMContentLoaded event

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

Всплытие да
Отменяемый Да (хотя указано как простое событие, которое не может быть отменено)
Интерфейс Event
Свойство обработчика событий нет

Разные события, load , должны быть использованы только для обнаружения полностью загруженной страницы. Это распространённая ошибка в использовании load , там где DOMContentLoaded было бы более уместным.

Синхронный JavaScript останавливает разбор DOM. Если вы хотите что бы DOM был разобран как можно быстрее после того как пользователь запросит страницу, вы должны сделать ваш JavaScript асинхронным and оптимизировать загрузку таблиц стилей. Если загружать как обычно, таблицы стилей тормозят разбор DOM так как они загружаются параллельно, «крадя» трафик у основного HTML документа.

Примеры

Основное применение

.addEventListener('DOMContentLoaded', (event) =>  console.log('DOM полностью загружен и разобран'); >); 

Отложенный DOMContentLoaded

script> document.addEventListener('DOMContentLoaded', (event) =>  console.log('DOM полностью загружен и разобран'); >); for( let i = 0; i  1000000000; i++) > // Этот синхронный скрипт откладывает разбор DOM, // так что событие DOMContentLoaded будет запущено позже. script> 

Проверка того, завершена ли загрузка

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

function doSomething()  console.info('DOM загружен'); > if (document.readyState === 'loading')  // Загрузка ещё не закончилась document.addEventListener('DOMContentLoaded', doSomething); > else  // `DOMContentLoaded` Уже сработал doSomething(); > 

Живые примеры

HTML

div class="controls"> button id="reload" type="button">Reloadbutton> div> div class="event-log"> label>Event log:label> textarea readonly class="event-log-contents" rows="8" cols="30">textarea> div> 
body  display: grid; grid-template-areas: "control log"; > .controls  grid-area: control; display: flex; align-items: center; justify-content: center; > .event-log  grid-area: log; > .event-log-contents  resize: none; > label, button  display: block; > #reload  height: 2rem; > 

JS

const log = document.querySelector('.event-log-contents'); const reload = document.querySelector('#reload'); reload.addEventListener('click', () =>  log.textContent =''; window.setTimeout(() =>  window.location.reload(true); >, 200); >); window.addEventListener('load', (event) =>  log.textContent = log.textContent + 'load\n'; >); document.addEventListener('readystatechange', (event) =>  log.textContent = log.textContent + `readystate: $document.readyState>\n`; >); document.addEventListener('DOMContentLoaded', (event) =>  log.textContent = log.textContent + `DOMContentLoaded\n`; >); 

Result

Спецификации

Браузерная совместимость

BCD tables only load in the browser

Смотрите также

Found a content problem with this page?

This page was last modified on 17 июл. 2023 г. by MDN contributors.

Your blueprint for a better internet.

MDN

Support

Our communities

Developers

Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2023 by individual mozilla.org contributors. Content available under a Creative Commons license.

Источник

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 not yet have loaded.
  • load – not only HTML is loaded, but also all the external resources: images, styles etc.
  • beforeunload/unload – the user is leaving the page.
  • 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:

document.addEventListener("DOMContentLoaded", ready); // not "document.onDOMContentLoaded = . "
  

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 tag, it needs to execute before continuing building the DOM. That’s a precaution, as scripts may want to modify DOM, and even document.write into it, so DOMContentLoaded has to wait.

So DOMContentLoaded definitely happens after such scripts:

    

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. This event is available via the onload property.

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 .

let analyticsData = < /* object with gathered data */ >; window.addEventListener("unload", function() < navigator.sendBeacon("/analytics", JSON.stringify(analyticsData)); >);
  • 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:

window.onbeforeunload = function() < return false; >;

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

window.onbeforeunload = function() < return "There are unsaved changes. Leave now?"; >;

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.

That may sound weird, but most browsers ignore event.preventDefault() .

Which means, following code may not work:

window.addEventListener("beforeunload", (event) => < // doesn't work, so this event handler doesn't do anything event.preventDefault(); >);

Instead, in such handlers one should set event.returnValue to a string to get the result similar to the code above:

window.addEventListener("beforeunload", (event) => < // works, same as returning from window.onbeforeunload event.returnValue = "There are unsaved changes. Leave now?"; >);

readyState

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

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.

function work() < /*. */ >if (document.readyState == 'loading') < // still loading, wait for the event document.addEventListener('DOMContentLoaded', work); >else < // DOM is ready! work(); >

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

// current state console.log(document.readyState); // print state changes document.addEventListener('readystatechange', () => console.log(document.readyState));

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:

   log('img onload'); 
  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).

  • document.readyState becomes interactive right before DOMContentLoaded . These two things actually mean the same.
  • document.readyState becomes complete when all resources ( iframe and img ) are loaded. Here we can see that it happens in about the same time as img.onload ( img is the last resource) and window.onload . Switching to complete state means the same as window.onload . The difference is that window.onload always works after all other load handlers.

Summary

Оцените статью