HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Веб-сайты в браузере, терминал и другие интерактивные системы, устроены по одному и тому же принципу.</p>
1 <p>Веб-сайты в браузере, терминал и другие интерактивные системы, устроены по одному и тому же принципу.</p>
2 <p>Они загружаются, затем переходят в режим ожидания и ждут, пока пользователь выполнит какое-либо действие. К таким действиям относятся клики, ввод текста, движения мыши, комбинации клавиш и так далее.</p>
2 <p>Они загружаются, затем переходят в режим ожидания и ждут, пока пользователь выполнит какое-либо действие. К таким действиям относятся клики, ввод текста, движения мыши, комбинации клавиш и так далее.</p>
3 <p>С точки зрения кода, существуют<strong>события</strong>, представляющие все действия. Рассмотрим некоторые распространенные события:</p>
3 <p>С точки зрения кода, существуют<strong>события</strong>, представляющие все действия. Рассмотрим некоторые распространенные события:</p>
4 <ul><li>click</li>
4 <ul><li>click</li>
5 <li>submit</li>
5 <li>submit</li>
6 <li>keyup</li>
6 <li>keyup</li>
7 <li>keydown</li>
7 <li>keydown</li>
8 <li>focus</li>
8 <li>focus</li>
9 <li>contextmenu</li>
9 <li>contextmenu</li>
10 <li>mouseover</li>
10 <li>mouseover</li>
11 <li>mousedown</li>
11 <li>mousedown</li>
12 <li>mouseup</li>
12 <li>mouseup</li>
13 </ul><p>События очень детализированы. Даже ввод буквы разбивается на два события: нажатие клавиши и ее отпускание. Кроме того, мы можем отличить горячие клавиши от обычного ввода с помощью события keypress.</p>
13 </ul><p>События очень детализированы. Даже ввод буквы разбивается на два события: нажатие клавиши и ее отпускание. Кроме того, мы можем отличить горячие клавиши от обычного ввода с помощью события keypress.</p>
14 <p>Любое событие будет связано с определенным элементом в DOM. Представьте, что вам нужно добавить новое поведение. Вы должны найти любой элемент и добавить коллбек addEventListener(). Программа будет вызывать его, когда произойдет событие:</p>
14 <p>Любое событие будет связано с определенным элементом в DOM. Представьте, что вам нужно добавить новое поведение. Вы должны найти любой элемент и добавить коллбек addEventListener(). Программа будет вызывать его, когда произойдет событие:</p>
15 <p>Каждый обработчик событий - это функция, которая вызывается при наступлении события. Эти обработчики запускаются один за другим в том порядке, в котором они были определены.</p>
15 <p>Каждый обработчик событий - это функция, которая вызывается при наступлении события. Эти обработчики запускаются один за другим в том порядке, в котором они были определены.</p>
16 <p>При необходимости мы можем удалить обработчик, хотя на практике это случается редко:</p>
16 <p>При необходимости мы можем удалить обработчик, хотя на практике это случается редко:</p>
17 <p>Мы можем вызывать события программно. Например, это относится к<a>focus</a>.</p>
17 <p>Мы можем вызывать события программно. Например, это относится к<a>focus</a>.</p>
18 <p>Представьте, что вы открываете чат и хотите написать в нем сообщение, но текст не появляется. Вам нужно сфокусироваться на поле ввода, чтобы набрать текст.</p>
18 <p>Представьте, что вы открываете чат и хотите написать в нем сообщение, но текст не появляется. Вам нужно сфокусироваться на поле ввода, чтобы набрать текст.</p>
19 <p>По умолчанию этого не происходит, и тут в дело вступаем мы:</p>
19 <p>По умолчанию этого не происходит, и тут в дело вступаем мы:</p>
20 <h2>Как тестировать</h2>
20 <h2>Как тестировать</h2>
21 <p>Чтобы понять, как события работают, нужно регулярно использовать их в браузере. Проще всего это делать так:</p>
21 <p>Чтобы понять, как события работают, нужно регулярно использовать их в браузере. Проще всего это делать так:</p>
22 <ol><li>Открываем консоль на любом сайте. Смотрим, где находятся элементы, с которыми мы хотим работать - например, кнопки или формы</li>
22 <ol><li>Открываем консоль на любом сайте. Смотрим, где находятся элементы, с которыми мы хотим работать - например, кнопки или формы</li>
23 <li>Выбираем любой элемент, который хотим отработать. Для простоты можно взять body</li>
23 <li>Выбираем любой элемент, который хотим отработать. Для простоты можно взять body</li>
24 <li>Добавляем к нему обработчик</li>
24 <li>Добавляем к нему обработчик</li>
25 <li>Вызываем событие и смотрим на реакцию</li>
25 <li>Вызываем событие и смотрим на реакцию</li>
26 </ol><p>Таким способом можно тестировать любые события на любых сайтах.</p>
26 </ol><p>Таким способом можно тестировать любые события на любых сайтах.</p>
27 <h2>Объект события</h2>
27 <h2>Объект события</h2>
28 <p>Каждое возникающее событие имеет связанную с ним информацию, которая зависит от типа события.</p>
28 <p>Каждое возникающее событие имеет связанную с ним информацию, которая зависит от типа события.</p>
29 <p>Например, событие click включает в себя щелчок и его координаты - точку на экране. Эта информация доступна через объект события, передаваемый обработчику события. Объекты событий передаются в обработчик всегда в виде одного параметра:</p>
29 <p>Например, событие click включает в себя щелчок и его координаты - точку на экране. Эта информация доступна через объект события, передаваемый обработчику события. Объекты событий передаются в обработчик всегда в виде одного параметра:</p>
30 <p>Каждый клик по кнопке, будет приводить к созданию нового объекта event со своими значениями, соответствующими текущему событию.</p>
30 <p>Каждый клик по кнопке, будет приводить к созданию нового объекта event со своими значениями, соответствующими текущему событию.</p>
31 <p>Объект event наполнен множеством свойств, которые проще всего изучать прямо в браузере.</p>
31 <p>Объект event наполнен множеством свойств, которые проще всего изучать прямо в браузере.</p>
32 <p>У разных событий есть как общие свойства, так и специфичные, например:</p>
32 <p>У разных событий есть как общие свойства, так и специфичные, например:</p>
33 <ul><li>у клика есть координаты</li>
33 <ul><li>у клика есть координаты</li>
34 <li>у нажатия клавиши - ее значение</li>
34 <li>у нажатия клавиши - ее значение</li>
35 </ul><p>Подробнее о свойствах смотрите в<a>документации</a>.</p>
35 </ul><p>Подробнее о свойствах смотрите в<a>документации</a>.</p>
36 <p>Общие свойства:</p>
36 <p>Общие свойства:</p>
37 <ul><li>event.target - DOM-элемент, на котором произошло событие. Через него проще всего добраться до данных, которые могут понадобиться после события</li>
37 <ul><li>event.target - DOM-элемент, на котором произошло событие. Через него проще всего добраться до данных, которые могут понадобиться после события</li>
38 <li>event.type - имя события, например<em>click</em>,<em>keyup</em>и так далее</li>
38 <li>event.type - имя события, например<em>click</em>,<em>keyup</em>и так далее</li>
39 </ul><p>Для примера посмотрим на задачу валидации вводимого пароля. Будем подсвечивать поле для ввода красной рамкой, если пароль слишком короткий:</p>
39 </ul><p>Для примера посмотрим на задачу валидации вводимого пароля. Будем подсвечивать поле для ввода красной рамкой, если пароль слишком короткий:</p>
40 <p><a>https://codepen.io/hexlet/pen/Exodyqp</a></p>
40 <p><a>https://codepen.io/hexlet/pen/Exodyqp</a></p>
41 <h2>Действие по умолчанию</h2>
41 <h2>Действие по умолчанию</h2>
42 <p>Для некоторых элементов у браузера есть<strong>действия по умолчанию</strong>- они выполняются при срабатывании определенных событий. Представим для примера, что мы повесили обработчик на клик по ссылке. Выполнив клик, мы внезапно перейдем на другую страницу - ту, которая указана в атрибуте href.</p>
42 <p>Для некоторых элементов у браузера есть<strong>действия по умолчанию</strong>- они выполняются при срабатывании определенных событий. Представим для примера, что мы повесили обработчик на клик по ссылке. Выполнив клик, мы внезапно перейдем на другую страницу - ту, которая указана в атрибуте href.</p>
43 <p>Это пример того самого действия по умолчанию, на которое никак не влияет наличие обработчиков. Чтобы отменить это действие, нужно вызвать метод event.preventDefault() внутри обработчика:</p>
43 <p>Это пример того самого действия по умолчанию, на которое никак не влияет наличие обработчиков. Чтобы отменить это действие, нужно вызвать метод event.preventDefault() внутри обработчика:</p>
44 <p>Действиями по умолчанию обладают следующие элементы:</p>
44 <p>Действиями по умолчанию обладают следующие элементы:</p>
45 <ul><li>Клик по ссылке приводит к переходу на страницу, указанную в<em>href</em>атрибуте</li>
45 <ul><li>Клик по ссылке приводит к переходу на страницу, указанную в<em>href</em>атрибуте</li>
46 <li>Клик на кнопку с типом<em>submit</em>начинает отправку формы на сервер</li>
46 <li>Клик на кнопку с типом<em>submit</em>начинает отправку формы на сервер</li>
47 <li>Вращение колесом мышки в textarea передвигает текст, если он не помещается</li>
47 <li>Вращение колесом мышки в textarea передвигает текст, если он не помещается</li>
48 <li>Вызов контекстного меню с помощью правого клика мышки</li>
48 <li>Вызов контекстного меню с помощью правого клика мышки</li>
49 </ul><h2>Конкуренция между событиями</h2>
49 </ul><h2>Конкуренция между событиями</h2>
50 <p>При выполнении обработчиков могут возникать новые события - как от действий пользователя, так и от самих обработчиков. При этом некоторые события всегда возникают целым блоком - например mouseup и click.</p>
50 <p>При выполнении обработчиков могут возникать новые события - как от действий пользователя, так и от самих обработчиков. При этом некоторые события всегда возникают целым блоком - например mouseup и click.</p>
51 <p>Это не означает, что выполнение кода сразу переключается на обработку этих событий. Вместо этого события складываются в очередь и выполняются последовательно.</p>
51 <p>Это не означает, что выполнение кода сразу переключается на обработку этих событий. Вместо этого события складываются в очередь и выполняются последовательно.</p>
52 <p>Но некоторые события все же берутся в обработку сразу. Это касается тех событий, которые генерируются программно - например, focus.</p>
52 <p>Но некоторые события все же берутся в обработку сразу. Это касается тех событий, которые генерируются программно - например, focus.</p>
53 <p>Возникает закономерный вопрос: "Что происходит со страницей во время выполнения обработчика?". Здесь возможны варианты.</p>
53 <p>Возникает закономерный вопрос: "Что происходит со страницей во время выполнения обработчика?". Здесь возможны варианты.</p>
54 <p>Представим, что обработчик выполняет некоторый код синхронно - например, занимается вычислениями. В этот момент блокируется все остальное и страница замирает. Если такое поведение длится слишком долго, то некоторые браузеры зависают, а другие - предлагают закрыть вкладку. Именно поэтому обработчики должны выполнять свою задачу максимально быстро.</p>
54 <p>Представим, что обработчик выполняет некоторый код синхронно - например, занимается вычислениями. В этот момент блокируется все остальное и страница замирает. Если такое поведение длится слишком долго, то некоторые браузеры зависают, а другие - предлагают закрыть вкладку. Именно поэтому обработчики должны выполнять свою задачу максимально быстро.</p>
55 <p>А что, если задача асинхронная - например, выполнение запроса к серверу? В таком случае все продолжает прекрасно работать, потому что HTTP-запросы не блокируют выполнение кода.</p>
55 <p>А что, если задача асинхронная - например, выполнение запроса к серверу? В таком случае все продолжает прекрасно работать, потому что HTTP-запросы не блокируют выполнение кода.</p>
56 <p>Событийная система возможна только в асинхронном коде. По сути, при загрузке страницы происходит инициализация и установка обработчиков. Как правило, дальше не выполняется никакой код. Вся страница находится в ожидании действий от пользователя.</p>
56 <p>Событийная система возможна только в асинхронном коде. По сути, при загрузке страницы происходит инициализация и установка обработчиков. Как правило, дальше не выполняется никакой код. Вся страница находится в ожидании действий от пользователя.</p>
57 <h2>Частые ошибки</h2>
57 <h2>Частые ошибки</h2>
58 <p>Довольно часто новички путаются в функциях. Вместо самой функции они передают в обработчик результат вызова функции:</p>
58 <p>Довольно часто новички путаются в функциях. Вместо самой функции они передают в обработчик результат вызова функции:</p>
59 <p>Функция handler() выполняется в момент навешивания обработчика на событие. Вместо самой функции будет передан результат вызова handler().</p>
59 <p>Функция handler() выполняется в момент навешивания обработчика на событие. Вместо самой функции будет передан результат вызова handler().</p>