Изучаем события в языке JavaScript
Основы событий в JavaScript
События позволяют реагировать на действия пользователя или изменения в браузере. Главный способ назначения обработчика - метод addEventListener. Он даёт гибкость и контроль, поэтому считается базовым решением.
Рекомендуемый способ: addEventListener
Метод element.addEventListener(event, handler, options) позволяет назначить несколько обработчиков на одно событие, легко удалять их и управлять фазой распространения.
// Пример: кнопка с обработчиком клика
const btn = document.querySelector('#myButton');
btn.addEventListener('click', function(event) {
console.log('Кнопка нажата');
});
Js event (события javascript)
Цель: универсальное и чистое назначение событий. Используется в большинстве современных проектов.
Как назначить обработчик через атрибут HTML?
В HTML можно написать onclick прямо в теге:
<button onclick="alert('Клик!')">Нажми меня</button>
события js (события javascript)
Этот способ удобен для быстрого прототипирования, но смешивает логику и представление, усложняет поддержку.
Типичные проблемы:
- Можно назначить только один обработчик на событие.
- Код в строке - плохая практика, трудно отлаживать.
- Нельзя использовать this по контексту элемента (внутри атрибута this ссылается на глобальный объект в строгом режиме).
Как задать обработчик через свойство DOM?
Присвоить функцию свойству element.onclick:
const btn = document.getElementById('btn');
btn.onclick = function() {
console.log('Нажато');
};
Подходит для простых сценариев, где нужен один обработчик.
Недостатки:
- Затирает предыдущий обработчик (только один на событие).
- Нельзя добавить несколько функций на одно событие.
- Сложно удалить обработчик, если анонимная функция.
Как получить информацию о событии (объект Event)?
Внутри обработчика первый аргумент - объект события. Он содержит тип, координаты, нажатую клавишу и т.д.
document.addEventListener('keydown', (e) => {
console.log('Нажата клавиша:', e.key);
});
Цель: доступ к деталям произошедшего действия. Обязательно нужно использовать в сложных интерактивных интерфейсах.
Ошибка: забыть параметр e, особенно при передаче другой функции.
Что такое всплытие и перехват событий?
Событие сначала проходит фазу перехвата (от window до цели), затем цель, затем всплывает обратно. По умолчанию обработчики срабатывают на фазе всплытия. Чтобы включить перехват, передайте {capture: true}.
document.body.addEventListener('click', () => console.log('body (всплытие)'), false);
document.body.addEventListener('click', () => console.log('body (перехват)'), {capture: true});
Цель: управление порядком выполнения обработчиков, реализация делегирования.
Путаница: если не указать capture, обработчик не сработает на фазе перехвата.
Как использовать делегирование событий?
Вместо назначения обработчика каждому элементу, вешаем один на родителя и проверяем event.target.
ul.addEventListener('click', function(e) {
if (e.target.tagName === 'LI') {
console.log('Клик по элементу списка:', e.target.textContent);
}
});
Цель: снижение числа обработчиков, работа с динамически добавляемыми элементами.
Ошибка: забыть проверить target, обработчик сработает на все клики внутри родителя.
Как остановить выполнение других обработчиков?
Методы event.stopPropagation() и event.stopImmediatePropagation(). Первый предотвращает всплытие/перехват, но остальные обработчики на текущем элементе выполнятся. Второй останавливает все последующие обработчики на том же элементе.
div.addEventListener('click', (e) => {
e.stopPropagation();
console.log('Только на div');
});
Цель: изоляция поведения, управление очередностью.
Злоупотребление stopPropagation нарушает делегирование.
Как отменить действие браузера по умолчанию?
Использовать event.preventDefault(). Например, для ссылки, чтобы не переходить по адресу.
document.querySelector('a').addEventListener('click', (e) => {
e.preventDefault();
console.log('Переход отменён');
});
Цель: кастомизация поведения форм, ссылок, контекстного меню.
Забыть вызвать preventDefault - форма отправится, страница перезагрузится.
Как удалить обработчик события?
Использовать removeEventListener с той же функцией (требуется сохранение ссылки на неё).
function handler() { console.log('клик'); }
btn.addEventListener('click', handler);
// Позже
btn.removeEventListener('click', handler);
Цель: очистка памяти, отключение временного поведения.
Если функция анонимная, удалить её нельзя. Нужно сохранять ссылку.
Как добавить обработчик только один раз?
Передать опцию { once: true } в addEventListener.
btn.addEventListener('click', () => {
console.log('Сработает ровно один раз');
}, { once: true });
Цель: ленивая инициализация, однократные действия.
Расширенные примеры работы с событиями
1. Обработка нескольких событий с одинаковой логикой
Можно передать массив типов событий или использовать общую функцию.
const input = document.querySelector('input');
['focus', 'blur', 'input'].forEach(type => {
input.addEventListener(type, (e) => {
console.log(`Событие ${type}`, e.target.value);
});
});
(при фокусе, потере фокуса и вводе текста в консоли появится соответствующее сообщение)
2. Делегирование с учётом вложенных элементов
Проверка closest позволяет обрабатывать клики на любом уровне вложенности внутри контейнера.
const list = document.querySelector('ul');
list.addEventListener('click', (e) => {
const li = e.target.closest('li');
if (li && list.contains(li)) {
console.log('Клик по:', li.textContent);
}
});
(клик по любому li внутри ul выводит его текст; клик по пустому пространству игнорируется)
3. Использование фазы перехвата для приоритетной обработки
Обработчик на стадии перехвата может предотвратить выполнение других обработчиков.
document.addEventListener('click', (e) => {
console.log('Перехват (документ)');
e.stopPropagation(); // остановит всплытие, но не перехват
}, { capture: true });
(при клике в любом месте сначала выведется 'Перехват (документ)', затем события на цели, но всплытия не будет)
4. Генерация пользовательских событий (CustomEvent)
Создание события с передачей данных.
const event = new CustomEvent('userLogin', {
detail: { username: 'John' }
});
document.addEventListener('userLogin', (e) => {
console.log('Пользователь вошёл:', e.detail.username);
});
document.dispatchEvent(event);
Пользователь вошёл: John
5. Управление множеством обработчиков с помощью объекта options
Параметры once, passive, signal.
const controller = new AbortController();
window.addEventListener('scroll', () => {
console.log('Скролл');
}, { passive: true, signal: controller.signal });
// Через некоторое время отмена
controller.abort();
(обработчик скролла будет вызван, но не помешает скроллингу; после abort удалён)
6. Обработка событий формы с валидацией
Предотвращение отправки при неверных данных.
document.querySelector('form').addEventListener('submit', (e) => {
const input = e.target.querySelector('input[required]');
if (!input.value.trim()) {
e.preventDefault();
console.log('Поле не заполнено');
}
});
(если поле пустое - форма не отправляется, сообщение в консоли)