Document ready на Javascript
JavaScript часто используется для взаимодействия с пользователем. В него включены возможности действий при определенных условиях. Каждый элемент на странице отображается в DOM (Document Object Model). У элемента есть атрибуты, включая реакции на определенные события.
События в JavaScript
DOM-объекты могут создавать события. Если в ответ на событие должна быть реакция, то для него устанавливают специальный обработчик. Различают разные типы событий:
- Действия мыши.
- События связанные с элементами управления.
- События клавиатуры.
- События документа.
- Связанные с CSS события.
Работу с событиями разделяют на две составляющие: отслеживание и реакция.
Отслеживание событий
Если нужна реакция на происходящее событие, то следует сообщить браузеру об этом. Есть три способа задать обработчик для большинства событий.
Указание в HTML как атрибута для конкретного объекта
Пример использования внутри HTML документа:
<script>
function countRabbits() {
for(let i=1; i<=3; i++) {
alert(«Кролик номер » + i);
}
}
</script><input type=»button» onclick=»countRabbits()» value=»Считать кроликов!»>
Данный код выведет три алерта при нажатии на элемент input.
Использование свойств DOM
Назначить функцию можно внутри html или используя возможности JaveScript.
<input id=»elem» type=»button» value=»Нажми меня!»>
<script>
elem.onclick = function() {
alert(‘Спасибо’);
};
</script>
Этот код переопределит реакцию на нажатие кнопки. Теперь после нажатия пользователь увидит алерт с сообщением “Спасибо”.
Функция addEventListener
Для приведенных выше примеров событие вызовет выполнение только одной функции. В отличие от них addEventListener может добавить функцию в список реакций на событие. Эта функция универсальна и в том, что она способна работать с любыми событиями.
Синтаксис:
element.addEventListener(event, handler[, options]);
Первым параметром должно быть передано событие, вторым – ссылка на функцию, третий параметр не является обязательным, в него могут быть включены дополнительные свойства.
Пример использования:
function handler() {
alert( ‘Спасибо!’ );
}input.addEventListener(«click», handler);
Добавление двух функций для одного события:
<input id=»elem» type=»button» value=»Нажми меня»/>
<script>
function handler1() {
alert(‘Спасибо!’);
};function handler2() {
alert(‘Спасибо ещё раз!’);
}elem.onclick = () => alert(«Привет»);
elem.addEventListener(«click», handler1); // Спасибо!
elem.addEventListener(«click», handler2); // Спасибо ещё раз!
</script>
Отличие от предыдущих методов будет и в способе отмены реакции. Для addEventListener есть противоположная функция removeEventListener. Для ее использования потребуется событие и функция переданная для реакции на него. Если чего-то нехватает, то обработчик отменен не будет.
Пример неправильной отмены:
elem.addEventListener( «click» , () => alert(‘Спасибо!’));
// ….
elem.removeEventListener( «click», () => alert(‘Спасибо!’));
Пример правильной отмены:
function handler() {
alert( ‘Спасибо!’ );
}input.addEventListener(«click», handler);
// ….
input.removeEventListener(«click», handler);
Реакция на событие
Реакцией служит функция, которую передали одним из перечисленных выше способов. В функцию могут быть переданы детали, которые будут полезны при обработке события. Эти детали передает специальный объект event, в котором могут содержаться координаты мыши или код использованной клавиши. Выполнение обработчика можно остановить используя функцию:
event.preventDefault()
События документа
Эти события зависят от состояния документа. Они не завязаны на конкретные элементы или действия пользователя на странице. Если пользователя необходимо предупредить о чем-то при уходе со страницы или запустить некую функцию сразу после загрузки страницы, то можно использовать события документа. У подобных событий отсутствуют действия по умолчанию.
Цикл жизни документа
При запросе страницы, первым будет получен файл html, в котором будут содержаться ссылки на другие файлы или скрипты для их загрузки. Файлы содержащие картинки, стили, библиотеки или скрипты, загружаются во время или после чтения исходного html документа.
Для всех этих состояний есть эвенты, которые можно использовать для запуска функций. Эти события отражаются в document.readyState, где находиться информация о текущем состоянии страницы. При попытке пользователя покинуть страницу можно вывести предупреждение или передать статистику на сервер.
domcontentloaded
При использовании этого события заданная функция запустится после загрузки html документа в браузер.
Пример использования:
<script>
function ready() {
alert(‘DOM готов’);// изображение ещё не загружено (если не было закешировано), так что размер будет 0x0
alert(`Размер изображения: ${img.offsetWidth}x${img.offsetHeight}`);
}document.addEventListener(«DOMContentLoaded», ready);
</script><img id=»img» src=»https://en.js.cx/clipart/train.gif?speed=1&cache=0″>
Данный код сработает при загрузке документа и выведет два алерта. При этом размер изображения может не отобразиться, поскольку ждать его загрузки для начала работы скрипту не обязательно.
Чтобы разобраться в каком порядке сработает обработчик для domcontentloaded рассмотрим следующий код:
<script>
document.addEventListener(«DOMContentLoaded», () => {
alert(«DOM готов!»);
});
</script><script src=»https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js»></script>
<script>
alert(«Библиотека загружена, встроенный скрипт выполнен»);
</script>
Первым пользователь увидит алерт содержащий фразу “Библиотека загружена, встроенный скрипт выполнен». Следующей выскочит “DOM готов!”. Это произойдет вследствие того, что domcontentloaded ждет загрузки документа для вызова обработчика, а содержащиеся на странице скрипты запускаются без какого-либо ожидания.
load
После загрузки всех файлов, включая скрипты, css-стили и картинки сработает этот обработчик. Отличие от предыдущего пункта в том, что перед запуском реакции скрипт будет ожидать загрузки всех файлов страницы.
Так как скрипт запускается в момент, когда он встретился, эта функция может быть полезна, она заставит ждать загрузки файлов среди которых могут находиться необходимые скрипту библиотеки.
Пример использования:
<script>
window.onload = function() {
alert(‘Страница загружена’);// к этому моменту страница загружена
alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
};
</script><img id=»img» src=»https://en.js.cx/clipart/train.gif?speed=1&cache=0″>
Данный скрипт выведет два сообщения. Первое уведомит о том, что страница загружена, второе покажет размер изображения.
Использование readyState
Если важно запустить функцию после загрузки страницы, но запуск обязателен, то перед установкой обработчика можно проверить переменную document.readyState. Пример использования с domcontentloaded:
function work() { /*…*/ }
if (document.readyState == ‘loading’) {
// ещё загружается, ждём события
document.addEventListener(‘DOMContentLoaded’, work);
} else {
// DOM готов!
work();
}
Состояние страницы отражено в переменной document.readyState. Возможные состояния страницы:
- “loading” – загрузка основного html файла;
- “interactive” – основной файл загружен, происходит загрузка остальных файлов;
- “complete” – все данные получены.
Можно установить соответствие между состояниями и работой domcontentloaded и load. Событие domcontentloaded произойдет при смене значения document.readyState с “loading” на “interactive”. События load сработает после того, как document.readyState примет значение “complete”.
Чтобы увидеть процесс изменения document.readyState на примере собственной страницы, добавьте в нее следующий скрипт:
<script>
// текущее состояние
console.log(document.readyState);// вывести изменения состояния
document.addEventListener(‘readystatechange’, () => console.log(document.readyState));
</script>
Как можно увидеть из примера, изменение этой переменной также можно использовать как событие и устанавливать для него обработчик.
unload
Перед тем как пользователь покинет страницу, можно передать данные на сервер. Действия выполняемые при этом событии не должны занимать много времени. После этого события сайт уже не может задержать пользователя, но может собрать статистику. Для передачи данных используется специальный метод navigator.sendBeacon(url, data), размер отправляемых данных не должен превышать 64 Кб. Пример использования:
let analyticsData = { /* объект с собранными данными */ };
window.addEventListener(«unload», function() {
navigator.sendBeacon(«/analytics», JSON.stringify(analyticsData));
});
beforeunload
Цель этого события предупредить пользователя о проблемах связанных с закрытием страницы, например потерей данных при заполнении формы или прохождении теста.
Пример вывода предупреждения при попытке закрыть или обновить страницу:
window.onbeforeunload = function() {
return false;
};
События документа в различных библиотеках
Такие библиотеки как vue или react уделяют больше внимания циклу жизни компонентов чем страницы. В них можно встретить функции, которые будут выполнены до создания компонента или при его уничтожении. В библиотеке jQuery есть несколько функций для обработки событий документа.
jQuery
Библиотека не вносит значительных изменений в работу кода. По сравнению с чистым javascript здесь просто используется меньше кода. Для нескольких функций можно использовать удобный вариант записи, который предлагает эта библиотека. Поддерживаемые функции для событий документа:
- .ready()
- .load()
- .unload()
Пример короткой записи:
$(function(){
// действия, которые необходимо выполнить после загрузки документа…});
Альтернативный способ запустить событие после загрузки страницы:
$(document).ready(function(){
// действия, которые необходимо выполнить после загрузки документа…});
Пример использования события load:
$(window).on(‘load’, function() {
// действия после полной загрузки страницы…
});
Пример использования unload:
$(window).unload(function(){
alert(«Пока, пользователь!»);
});
В этой библиотеке есть несколько способов присвоения обработчиков для событий и можно пользоваться любым из них.