JS: DOM API
Теория: Введение в события
Веб-сайты в браузере, терминал и другие интерактивные системы, устроены по одному и тому же принципу.
Они загружаются, затем переходят в режим ожидания и ждут, пока пользователь выполнит какое-либо действие. К таким действиям относятся клики, ввод текста, движения мыши, комбинации клавиш и так далее.
С точки зрения кода, существуют события, представляющие все действия. Рассмотрим некоторые распространенные события:
clicksubmitkeyupkeydownfocuscontextmenumouseovermousedownmouseup
События очень детализированы. Даже ввод буквы разбивается на два события: нажатие клавиши и ее отпускание. Кроме того, мы можем отличить горячие клавиши от обычного ввода с помощью события keypress.
Любое событие будет связано с определенным элементом в DOM. Представьте, что вам нужно добавить новое поведение. Вы должны найти любой элемент и добавить коллбек addEventListener(). Программа будет вызывать его, когда произойдет событие:
Каждый обработчик событий — это функция, которая вызывается при наступлении события. Эти обработчики запускаются один за другим в том порядке, в котором они были определены.
При необходимости мы можем удалить обработчик, хотя на практике это случается редко:
Мы можем вызывать события программно. Например, это относится к focus.
Представьте, что вы открываете чат и хотите написать в нем сообщение, но текст не появляется. Вам нужно сфокусироваться на поле ввода, чтобы набрать текст.
По умолчанию этого не происходит, и тут в дело вступаем мы:
Как тестировать
Чтобы понять, как события работают, нужно регулярно использовать их в браузере. Проще всего это делать так:
- Открываем консоль на любом сайте. Смотрим, где находятся элементы, с которыми мы хотим работать — например, кнопки или формы
- Выбираем любой элемент, который хотим отработать. Для простоты можно взять
body - Добавляем к нему обработчик
- Вызываем событие и смотрим на реакцию
Таким способом можно тестировать любые события на любых сайтах.
Объект события
Каждое возникающее событие имеет связанную с ним информацию, которая зависит от типа события.
Например, событие click включает в себя щелчок и его координаты — точку на экране. Эта информация доступна через объект события, передаваемый обработчику события. Объекты событий передаются в обработчик всегда в виде одного параметра:
Каждый клик по кнопке, будет приводить к созданию нового объекта event со своими значениями, соответствующими текущему событию.
Объект event наполнен множеством свойств, которые проще всего изучать прямо в браузере.
У разных событий есть как общие свойства, так и специфичные, например:
- у клика есть координаты
- у нажатия клавиши — ее значение
Подробнее о свойствах смотрите в документации.
Общие свойства:
event.target— DOM-элемент, на котором произошло событие. Через него проще всего добраться до данных, которые могут понадобиться после событияevent.type— имя события, например click, keyup и так далее
Для примера посмотрим на задачу валидации вводимого пароля. Будем подсвечивать поле для ввода красной рамкой, если пароль слишком короткий:
https://codepen.io/hexlet/pen/Exodyqp
Действие по умолчанию
Для некоторых элементов у браузера есть действия по умолчанию — они выполняются при срабатывании определенных событий. Представим для примера, что мы повесили обработчик на клик по ссылке. Выполнив клик, мы внезапно перейдем на другую страницу — ту, которая указана в атрибуте href.
Это пример того самого действия по умолчанию, на которое никак не влияет наличие обработчиков. Чтобы отменить это действие, нужно вызвать метод event.preventDefault() внутри обработчика:
Действиями по умолчанию обладают следующие элементы:
- Клик по ссылке приводит к переходу на страницу, указанную в href атрибуте
- Клик на кнопку с типом submit начинает отправку формы на сервер
- Вращение колесом мышки в
textareaпередвигает текст, если он не помещается - Вызов контекстного меню с помощью правого клика мышки
Конкуренция между событиями
При выполнении обработчиков могут возникать новые события — как от действий пользователя, так и от самих обработчиков. При этом некоторые события всегда возникают целым блоком — например mouseup и click.
Это не означает, что выполнение кода сразу переключается на обработку этих событий. Вместо этого события складываются в очередь и выполняются последовательно.
Но некоторые события все же берутся в обработку сразу. Это касается тех событий, которые генерируются программно — например, focus.
Возникает закономерный вопрос: «Что происходит со страницей во время выполнения обработчика?». Здесь возможны варианты.
Представим, что обработчик выполняет некоторый код синхронно — например, занимается вычислениями. В этот момент блокируется все остальное и страница замирает. Если такое поведение длится слишком долго, то некоторые браузеры зависают, а другие — предлагают закрыть вкладку. Именно поэтому обработчики должны выполнять свою задачу максимально быстро.
А что, если задача асинхронная — например, выполнение запроса к серверу? В таком случае все продолжает прекрасно работать, потому что HTTP-запросы не блокируют выполнение кода.
Событийная система возможна только в асинхронном коде. По сути, при загрузке страницы происходит инициализация и установка обработчиков. Как правило, дальше не выполняется никакой код. Вся страница находится в ожидании действий от пользователя.
Частые ошибки
Довольно часто новички путаются в функциях. Вместо самой функции они передают в обработчик результат вызова функции:
Функция handler() выполняется в момент навешивания обработчика на событие. Вместо самой функции будет передан результат вызова handler().



