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>