События в JavaScript: addEventListener на практике
Содержание
О проверке кода. Примеры не запускались в браузере — в отличие от материалов по Node.js с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».
Интерактивность страницы — это реакция на события: клики, ввод, отправку форм. В JavaScript события — целая система со своими правилами. Разберём то, что нужно на практике.
addEventListener вместо onclick
const btn = document.querySelector('.btn');
// ❌ старый способ — только ОДИН обработчик
btn.onclick = () => console.log('клик');
btn.onclick = () => console.log('другой'); // перезаписал первый!
// ✅ современный — сколько угодно обработчиков
btn.addEventListener('click', () => console.log('первый'));
btn.addEventListener('click', () => console.log('второй')); // оба сработают
addEventListener — стандарт навешивания событий. В отличие от onclick, он позволяет несколько обработчиков на одно событие, поддерживает опции и корректное снятие. Свойство onclick хранит только один обработчик и перезаписывается — этого достаточно редко.
Частые типы событий: click, input (ввод в поле), submit (отправка формы), keydown (нажатие клавиши), mouseover, change, scroll.
Объект event
Обработчик автоматически получает объект события:
btn.addEventListener('click', (event) => {
event.target; // элемент, по которому кликнули
event.type; // 'click'
event.currentTarget; // элемент, на котором висит обработчик
});
input.addEventListener('input', (event) => {
event.target.value; // текущий текст в поле
});
document.addEventListener('keydown', (event) => {
event.key; // 'Enter', 'Escape', 'a'...
});
event содержит всю информацию о событии. Самое частое — event.target (элемент-источник) и event.target.value (для полей ввода). Для клавиатуры — event.key, для мыши — event.clientX/clientY. Через этот объект и управляют поведением.
preventDefault: отменить действие браузера
// не дать форме перезагрузить страницу
form.addEventListener('submit', (event) => {
event.preventDefault(); // отменяем стандартную отправку
// ...обрабатываем данные через JavaScript
});
// не переходить по ссылке
link.addEventListener('click', (event) => {
event.preventDefault();
});
event.preventDefault() отменяет стандартную реакцию браузера. Отправка формы перезагружает страницу, клик по ссылке ведёт на URL, клавиши прокручивают — всё это можно отменить, чтобы обработать самому. Это первое, что делают в обработчике submit при работе с формой через JavaScript.
Всплытие событий
document.querySelector('#parent').addEventListener('click', () => {
console.log('сработал родитель');
});
document.querySelector('#child').addEventListener('click', () => {
console.log('сработал ребёнок');
});
// клик по child выведет: 'сработал ребёнок', потом 'сработал родитель'
- 1 Клик по кнопкеСобытие рождается на самом элементе (target)
- 2 Всплывает к родителюСрабатывают обработчики на div-контейнере
- 3 Дальше вверхsection → body → document — по всей цепочке
- 4 stopPropagation()Останавливает всплытие, если нужно
Событие сначала срабатывает на самом элементе, затем поднимается («всплывает») вверх по родителям до document. Клик по кнопке внутри div вызовет обработчики и кнопки, и div, и всех родителей. Это не баг, а фундамент делегирования событий — мощного приёма. Остановить всплытие можно через event.stopPropagation(), но применяйте его осознанно — он ломает делегирование.
Снятие обработчика
// ❌ анонимную функцию снять НЕЛЬЗЯ — на неё нет ссылки
btn.addEventListener('click', () => console.log('клик'));
// removeEventListener не к чему привязать
// ✅ именованная функция — снимается корректно
function handleClick() { console.log('клик'); }
btn.addEventListener('click', handleClick);
btn.removeEventListener('click', handleClick); // работает
// одноразовый обработчик — снимется сам
btn.addEventListener('click', handleClick, { once: true });
removeEventListener требует ту же функцию, что была при добавлении — значит, обработчик должен быть именованным, анонимную стрелку снять невозможно. Забытые обработчики — источник утечек памяти в долгоживущих приложениях. Для одноразовых событий удобна опция { once: true } — обработчик снимется автоматически после первого срабатывания.
Полезные опции
el.addEventListener('scroll', handler, { passive: true }); // не блокирует прокрутку
el.addEventListener('click', handler, { once: true }); // один раз
el.addEventListener('click', handler, { capture: true }); // на фазе погружения
{ passive: true } для scroll и touch говорит браузеру, что обработчик не вызовет preventDefault — это ускоряет прокрутку. Опции — то, чего лишён старый onclick, ещё одна причина использовать addEventListener.
Смежные темы: делегирование событий — один обработчик на многих; поиск элементов; валидация форм — preventDefault на submit. Полный список — в уроках JavaScript.