Работа с событиями: addEventListener, removeEventListener

Введение в обработку событий 🎭

События — это основа интерактивности в JavaScript. Любое действие пользователя (клик, наведение, ввод текста) генерирует событие, которое можно обработать и превратить в динамическое поведение страницы.

// Простейший пример обработки клика
const button = document.querySelector('button');
button.onclick = function() {
  console.log('Кнопка нажата!');
};

Но такой подход имеет серьёзный недостаток — мы можем назначить только один обработчик на событие. Для современных приложений этого недостаточно! Выход есть — addEventListener.


addEventListener: гибкость и контроль ✨

Метод addEventListener позволяет добавлять несколько обработчиков к одному событию элемента. Его базовый синтаксис:

element.addEventListener(event, handler[, options]);

Практический пример с пояснениями

const magicButton = document.getElementById('magic-btn');

// Первый обработчик
magicButton.addEventListener('click', function() {
  console.log('Произошла магия! ✨');
});

// Второй обработчик (ничего не перезаписывает)
magicButton.addEventListener('click', function() {
  this.style.backgroundColor = 'gold';
});

💡 Обратите внимание: мы использовали this внутри обработчика. В контексте события this ссылается на элемент, к которому привязан обработчик.


Параметры addEventListener: capture, passive и once 🛠️

Третий аргумент addEventListener — объект options с важными настройками:

Опция Тип Описание
capture boolean Фаза обработки (true — захват, false — всплытие)
passive boolean Указывает, что обработчик НЕ будет вызывать preventDefault()
once boolean Автоматическое удаление обработчика после первого срабатывания
// Обработчик сработает только один раз
document.addEventListener('scroll', function() {
  console.log('Прокрутка произошла!');
}, { once: true });

removeEventListener: правильная очистка памяти 🧹

Чтобы удалить обработчик события, нужно явно вызвать removeEventListener с теми же аргументами, что и при добавлении.

function handleClick() {
  console.log('Этот обработчик будет удалён');
}

const btn = document.querySelector('#demo-btn');

// Добавляем
btn.addEventListener('click', handleClick);

// Удаляем (аргументы должны совпадать!)
btn.removeEventListener('click', handleClick);

⚠️ Важно: если обработчик анонимный, удалить его невозможно! Всегда сохраняйте ссылку на функцию, если планируете её удалять.


Реальный кейс: модальное окно с грамотной подпиской/отпиской 🖼️

Давайте создадим модальное окно, которое:

  1. Открывается по клику на кнопку
  2. Закрывается по клику на крестик или вне модалки
  3. Корректно очищает все обработчики при закрытии
const modal = document.querySelector('.modal');
const openBtn = document.querySelector('.open-modal');
const closeBtn = modal.querySelector('.close');

function openModal() {
  modal.style.display = 'block';
  document.addEventListener('click', closeOnBackdrop);
}

function closeModal() {
  modal.style.display = 'none';
  document.removeEventListener('click', closeOnBackdrop);
}

function closeOnBackdrop(e) {
  if (!modal.contains(e.target) && e.target !== openBtn) {
    closeModal();
  }
}

openBtn.addEventListener('click', openModal);
closeBtn.addEventListener('click', closeModal);

Именованные функции vs Анонимные: когда что использовать 🤔

Подход Плюсы Минусы Когда использовать
Именованные функции Можно удалить, читаемость Занимают место в области видимости Для обработчиков, которые нужно удалять
Анонимные функции Компактность, локальность Нельзя удалить Для одноразовых обработчиков
// Хороший пример именованной функции
function handleFormSubmit(e) {
  e.preventDefault();
  console.log('Форма отправлена!');
}

form.addEventListener('submit', handleFormSubmit);

// Позже можно удалить
form.removeEventListener('submit', handleFormSubmit);

Современные практики: делегирование событий 🎯

Вместо добавления обработчиков к множеству элементов, можно использовать делегирование — подписаться на событие у родителя и фильтровать события по целевым элементам.

document.querySelector('.item-list').addEventListener('click', function(e) {
  if (e.target.classList.contains('item')) {
    console.log('Кликнут элемент:', e.target.textContent);
  }
});

Это особенно полезно для динамически добавляемых элементов или больших списков!


Итоги и лучшие практики 🏆

  1. Всегда предпочитайте addEventListener простым свойствам типа onclick
  2. Для удаления обработчиков сохраняйте ссылки на функции
  3. Используйте делегирование событий для динамических элементов
  4. Опция { once: true } — ваш друг для одноразовых событий
  5. Не забывайте про фазы событий (capture/bubble) при сложной логике

Теперь вы вооружены знаниями для профессиональной работы с событиями в JavaScript! 🚀

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео