- Страница: DOMContentLoaded, load, beforeunload, unload
- DOMContentLoaded
- DOMContentLoaded и скрипты
- DOMContentLoaded и стили
- Встроенное в браузер автозаполнение
- window.onload
- window.onunload
- window.onbeforeunload
- readyState
- window.onload vs document.onload
- 9 Answers 9
- When do they fire?
- How well are they supported?
- window.onload vs
- 13 Answers 13
Страница: DOMContentLoaded, load, beforeunload, unload
У жизненного цикла HTML-страницы есть три важных события:
- DOMContentLoaded – браузер полностью загрузил HTML, было построено DOM-дерево, но внешние ресурсы, такие как картинки и стили, могут быть ещё не загружены.
- load – браузер загрузил HTML и внешние ресурсы (картинки, стили и т.д.).
- beforeunload/unload – пользователь покидает страницу.
Каждое из этих событий может быть полезно:
- Событие DOMContentLoaded – DOM готов, так что обработчик может искать DOM-узлы и инициализировать интерфейс.
- Событие load – внешние ресурсы были загружены, стили применены, размеры картинок известны и т.д.
- Событие beforeunload – пользователь покидает страницу. Мы можем проверить, сохранил ли он изменения и спросить, на самом ли деле он хочет уйти.
- unload – пользователь почти ушёл, но мы всё ещё можем запустить некоторые операции, например, отправить статистику.
Давайте рассмотрим эти события подробнее.
DOMContentLoaded
Событие DOMContentLoaded срабатывает на объекте document .
Мы должны использовать addEventListener , чтобы поймать его:
В этом примере обработчик DOMContentLoaded запустится, когда документ загрузится, так что он увидит все элементы, включая расположенный ниже .
Но он не дожидается, пока загрузится изображение. Поэтому alert покажет нулевой размер.
На первый взгляд событие DOMContentLoaded очень простое. DOM-дерево готово – получаем событие. Хотя тут есть несколько особенностей.
DOMContentLoaded и скрипты
Когда браузер обрабатывает HTML-документ и встречает тег
В примере выше мы сначала увидим «Библиотека загружена…», а затем «DOM готов!» (все скрипты выполнены).
Есть два исключения из этого правила:
- Скрипты с атрибутом async , который мы рассмотрим немного позже, не блокируют DOMContentLoaded.
- Скрипты, сгенерированные динамически при помощи document.createElement(‘script’) и затем добавленные на страницу, также не блокируют это событие.
DOMContentLoaded и стили
Внешние таблицы стилей не затрагивают DOM, поэтому DOMContentLoaded их не ждёт.
Но здесь есть подводный камень. Если после стилей у нас есть скрипт, то этот скрипт должен дождаться, пока загрузятся стили:
Причина в том, что скрипту может понадобиться получить координаты или другие свойства элементов, зависящих от стилей, как в примере выше. Естественно, он должен дождаться, пока стили загрузятся.
Так как DOMContentLoaded дожидается скриптов, то теперь он так же дожидается и стилей перед ними.
Встроенное в браузер автозаполнение
Firefox, Chrome и Opera автоматически заполняют поля при наступлении DOMContentLoaded .
Например, если на странице есть форма логина и пароля и браузер запомнил значения, то при наступлении DOMContentLoaded он попытается заполнить их (если получил разрешение от пользователя).
Так что, если DOMContentLoaded откладывается из-за долгой загрузки скриптов, в свою очередь – откладывается автозаполнение. Вы наверняка замечали, что на некоторых сайтах (если вы используете автозаполнение в браузере) поля логина и пароля не заполняются мгновенно, есть некоторая задержка до полной загрузки страницы. Это и есть ожидание события DOMContentLoaded .
window.onload
Событие load на объекте window наступает, когда загрузилась вся страница, включая стили, картинки и другие ресурсы.
В примере ниже правильно показаны размеры картинки, потому что window.onload дожидается всех изображений:
window.onunload
Когда посетитель покидает страницу, на объекте window генерируется событие unload . В этот момент стоит совершать простые действия, не требующие много времени, вроде закрытия связанных всплывающих окон.
Обычно здесь отсылают статистику.
Предположим, мы собрали данные о том, как используется страница: клики, прокрутка, просмотры областей страницы и так далее.
Естественно, событие unload – это тот момент, когда пользователь нас покидает и мы хотим сохранить эти данные.
Для этого существует специальный метод navigator.sendBeacon(url, data) , описанный в спецификации https://w3c.github.io/beacon/.
Он посылает данные в фоне. Переход к другой странице не задерживается: браузер покидает страницу, но всё равно выполняет sendBeacon .
Его можно использовать вот так:
- Отсылается POST-запрос.
- Мы можем послать не только строку, но так же формы и другие форматы, как описано в главе Fetch, но обычно это строковый объект.
- Размер данных ограничен 64 Кб.
К тому моменту, как sendBeacon завершится, браузер наверняка уже покинет страницу, так что возможности обработать ответ сервера не будет (для статистики он обычно пустой).
Для таких запросов с закрывающейся страницей есть специальный флаг keepalive в методе fetch для общих сетевых запросов. Вы можете найти больше информации в главе Fetch API.
Если мы хотим отменить переход на другую страницу, то здесь мы этого сделать не сможем. Но сможем в другом месте – в событии onbeforeunload .
window.onbeforeunload
Если посетитель собирается уйти со страницы или закрыть окно, обработчик beforeunload попросит дополнительное подтверждение.
Если мы отменим это событие, то браузер спросит посетителя, уверен ли он.
Вы можете попробовать это, запустив следующий код и затем перезагрузив страницу:
По историческим причинам возврат непустой строки так же считается отменой события. Когда-то браузеры использовали её в качестве сообщения, но, как указывает современная спецификация, они не должны этого делать.
Поведение было изменено, потому что некоторые веб-разработчики злоупотребляли этим обработчиком события, показывая вводящие в заблуждение и надоедливые сообщения. Так что, прямо сейчас старые браузеры всё ещё могут показывать строку как сообщение, но в остальных – нет возможности настроить показ сообщения пользователям.
readyState
Что произойдёт, если мы установим обработчик DOMContentLoaded после того, как документ загрузился?
Естественно, он никогда не запустится.
Есть случаи, когда мы не уверены, готов документ или нет. Мы бы хотели, чтобы наша функция исполнилась, когда DOM загрузился, будь то сейчас или позже.
Свойство document.readyState показывает нам текущее состояние загрузки.
Есть три возможных значения:
- «loading» – документ загружается.
- «interactive» – документ был полностью прочитан.
- «complete» – документ был полностью прочитан и все ресурсы (такие как изображения) были тоже загружены.
Так что мы можем проверить document.readyState и, либо установить обработчик, либо, если документ готов, выполнить код сразу же.
Например, вот так:
Также есть событие readystatechange , которое генерируется при изменении состояния, так что мы можем вывести все эти состояния таким образом:
Событие readystatechange – альтернативный вариант отслеживания состояния загрузки документа, который появился очень давно. На сегодняшний день он используется редко.
Для полноты картины давайте посмотрим на весь поток событий:
Здесь документ с , и обработчиками, которые логируют события:
Рабочий пример есть в песочнице.
- [1] начальный readyState:loading
- [2] readyState:interactive
- [2] DOMContentLoaded
- [3] iframe onload
- [4] img onload
- [4] readyState:complete
- [4] window onload
Цифры в квадратных скобках обозначают примерное время события. События, отмеченные одинаковой цифрой, произойдут примерно в одно и то же время (± несколько миллисекунд).
window.onload vs document.onload
Which is more widely supported: window.onload or document.onload ?
9 Answers 9
When do they fire?
- By default, it is fired when the entire page loads, including its content (images, CSS, scripts, etc.).
In some browsers it now takes over the role of document.onload and fires when the DOM is ready as well.
- It is called when the DOM is ready which can be prior to images and other external content is loaded.
How well are they supported?
window.onload appears to be the most widely supported. In fact, some of the most modern browsers have in a sense replaced document.onload with window.onload .
Browser support issues are most likely the reason why many people are starting to use libraries such as jQuery to handle the checking for the document being ready, like so:
For the purpose of history. window.onload vs body.onload :
A similar question was asked on codingforums a while back regarding the usage of window.onload over body.onload . The result seemed to be that you should use window.onload because it is good to separate your structure from the action.
The general idea is that window.onload fires when the document’s window is ready for presentation and document.onload fires when the DOM tree (built from the markup code within the document) is completed.
Ideally, subscribing to DOM-tree events, allows offscreen-manipulations through Javascript, incurring almost no CPU load. Contrarily, window.onload can take a while to fire, when multiple external resources have yet to be requested, parsed and loaded.
►Test scenario:
To observe the difference and how your browser of choice implements the aforementioned event handlers, simply insert the following code within your document’s — — tag.
►Result:
Here is the resulting behavior, observable for Chrome v20 (and probably most current browsers).
- No document.onload event.
- onload fires twice when declared inside the , once when declared inside the (where the event then acts as document.onload ).
- counting and acting dependent on the state of the counter allows to emulate both event behaviors.
- Alternatively declare the window.onload event handler within the confines of the HTML- element.
►Example Project:
The code above is taken from this project’s codebase ( index.html and keyboarder.js ).
For a list of event handlers of the window object, please refer to the MDN documentation.
window.onload vs
What exactly is the difference between the window.onload event and the onload event of the body tag? when do I use which and how should it be done correctly?
13 Answers 13
window.onload = myOnloadFunc and are different ways of using the same event. Using window.onload is less obtrusive though — it takes your JavaScript out of the HTML.
All of the common JavaScript libraries, Prototype, ExtJS, Dojo, JQuery, YUI, etc. provide nice wrappers around events that occur as the document is loaded. You can listen for the window onLoad event, and react to that, but onLoad is not fired until all resources have been downloaded, so your event handler won’t be executed until that last huge image has been fetched. In some cases that’s exactly what you want, in others you might find that listening for when the DOM is ready is more appropriate — this event is similar to onLoad but fires without waiting for images, etc. to download.
There is no difference, but you should not use either.
In many browsers, the window.onload event is not triggered until all images have loaded, which is not what you want. Standards based browsers have an event called DOMContentLoaded which fires earlier, but it is not supported by IE (at the time of writing this answer). I’d recommend using a javascript library which supports a cross browser DOMContentLoaded feature, or finding a well written function you can use. jQuery’s $(document).ready() , is a good example.
window.onload can work without body. Create page with only the script tags and open it in a browser. The page doesn’t contain any body, but it still works..
I prefer, generally, to not use the > event. I think it’s cleaner to keep behavior separated from content as much as possible.
That said, there are occasions (usually pretty rare for me) where using body onload can give a slight speed boost.
I like to use Prototype so I generally put something like this in the > of my page:
The above are tricks I learned here. I’m very fond of the concept of attach event handlers outside of the HTML.
(Edit to correct spelling mistake in code.)
‘so many subjective answers to an objective question. «Unobtrusive» JavaScript is superstition like the old rule to never use gotos. Write code in a way that helps you reliably accomplish your goal, not according to someone’s trendy religious beliefs.
Anyone who finds:
to be overly distracting is overly pretentious and doesn’t have their priorities straight.
I normally put my JavaScript code in a separate .js file, but I find nothing cumbersome about hooking event handlers in HTML, which is valid HTML by the way.
window.onload — Called after all DOM, JS files, Images, Iframes, Extensions and others completely loaded. This is equal to $(window).load(function() <>);
body onload=»» — Called once DOM loaded. This is equal to $(document).ready(function() <>);
There is no difference .
So principially you could use both (one at a time !-)
But for the sake of readability and for the cleanliness of the html-code I always prefer the window.onload !o]
If you’re trying to write unobtrusive JS code (and you should be), then you shouldn’t use .
It is my understanding that different browsers handle these two slightly differently but they operate similarly. In most browsers, if you define both, one will be ignored.
Think of onload like any other attribute. On an input box, for example, you could put:
Or you could call:
The onload attribute works the same way, except that it takes a function as its value instead of a string like the value attribute does. That also explains why you can «only use one of them» — calling window.onload reassigns the value of the onload attribute for the body tag.
Also, like others here are saying, usually it is cleaner to keep style and javascript separated from the content of the page, which is why most people advise to use window.onload or like jQuery’s ready function.
should override window.onload.
With , document.body.onload might be null, undefined or a function depending on the browser (although getAttribute(«onload») should be somewhat consistent for getting the body of the anonymous function as a string). With window.onload, when you assign a function to it, window.onload will be a function consistently across browsers. If that matters to you, use window.onload.
window.onload is better for separating the JS from your content anyway. There’s not much reason to use anyway when you can use window.onload.
In Opera, the event target for window.onload and (and even window.addEventListener(«load», func, false)) will be the window instead of the document like in Safari and Firefox. But, ‘this’ will be the window across browsers.
What this means is that, when it matters, you should wrap the crud and make things consistent or use a library that does it for you.