$ sudo teach IT
МОДУЛЬ 9 · УРОК 5

События и обработчики

Пользователь нажал кнопку — что-то произошло. Ввёл текст — снова что-то произошло. Это и есть события. Сейчас научимся их слушать и реагировать на них — это основа интерактивности любого сайта.

⏱ ~25 минут 🎓 Новичок 🌐 DOM API

🔔 Что такое событие?

Событие — это сигнал о том, что что-то произошло в браузере. Пользователь кликнул мышью — событие. Нажал клавишу — событие. Страница загрузилась — тоже событие. Браузер постоянно следит за действиями и генерирует события.

Наша задача — сказать браузеру: «Когда вот это событие случится на вот этом элементе — вызови мою функцию». Такая функция называется обработчик событий (event handler) или слушатель (listener).

🖱️
click

Клик мышью по элементу

⌨️
keydown

Нажатие клавиши

✏️
input

Ввод текста в поле

📋
submit

Отправка формы

🔄
change

Изменение значения (checkbox, select)

🖱️
mouseover

Наведение курсора

👂 addEventListener — слушаем событие

Главный инструмент — метод addEventListener. Он принимает два обязательных аргумента: название события (строка) и функцию-обработчик (колбэк).

const button = document.querySelector('#myButton');

button.addEventListener('click', function() {
  console.log('Кнопку нажали!');
});

// Или через стрелочную функцию (чаще используют):
button.addEventListener('click', () => {
  console.log('Кнопку нажали!');
});

💡 Почему addEventListener, а не onclick? Старый способ — element.onclick = fn — работает, но у него один минус: можно добавить только один обработчик. Второй присвоение перезапишет первый. addEventListener позволяет добавлять сколько угодно обработчиков на одно событие.

Можно также удалить обработчик методом removeEventListener — но для этого нужно передать ту же самую функцию, поэтому анонимные стрелочные функции нельзя удалить:

function handleClick() {
  console.log('Клик!');
}

button.addEventListener('click', handleClick);
// Позже — удаляем:
button.removeEventListener('click', handleClick);

📦 Объект события: event

Когда событие происходит, браузер автоматически передаёт в обработчик специальный объект — объект события. По традиции его называют event или просто e. Он содержит кучу полезной информации о том, что именно произошло.

button.addEventListener('click', (event) => {
  console.log(event.target);     // элемент, на котором произошло событие
  console.log(event.type);       // тип события: 'click'
  console.log(event.clientX);    // координаты клика по X
  console.log(event.clientY);    // координаты клика по Y
});
event.target

Элемент, на котором непосредственно произошло событие. Если кликнули по кнопке — это кнопка.

event.preventDefault()

Отменяет стандартное поведение браузера. Например, не даёт ссылке перейти по URL или форме перезагрузить страницу.

event.stopPropagation()

Останавливает всплытие события вверх по дереву DOM. Подробнее — в следующем разделе.

// Пример: отменяем переход по ссылке
const link = document.querySelector('a');

link.addEventListener('click', (event) => {
  event.preventDefault(); // браузер НЕ перейдёт по href
  console.log('Клик по ссылке — но переход отменён');
});

🫧 Всплытие событий (Event Bubbling)

Представьте структуру: внутри <div> есть <p>, внутри <p> — кнопка <button>. Если кликнуть по кнопке — сработает обработчик кнопки. Но после этого событие всплывает вверх: сработает обработчик <p>, затем <div>, затем <body>, затем document.

🫧 Аналогия: событие — как пузырёк воздуха под водой. Оно появляется внизу (на конкретном элементе) и поднимается вверх по DOM-дереву.

// HTML: <div id="parent"><button id="child">Клик</button></div>

document.querySelector('#parent').addEventListener('click', () => {
  console.log('Сработал родитель!');
});

document.querySelector('#child').addEventListener('click', (e) => {
  console.log('Сработал ребёнок!');
  e.stopPropagation(); // останавливаем всплытие — родитель НЕ сработает
});

Всплытие — мощная особенность. Можно поставить один обработчик на родителя и обрабатывать клики по всем дочерним элементам. Это называется делегирование событий.

// Делегирование: один обработчик на список
const list = document.querySelector('#taskList');

list.addEventListener('click', (event) => {
  // event.target — это конкретный <li> на который кликнули
  if (event.target.tagName === 'LI') {
    event.target.classList.toggle('done');
  }
});

💻 Практические примеры

📊 Пример 1: Счётчик кликов

let count = 0;
const btn = document.querySelector('#counter-btn');
const display = document.querySelector('#count-display');

btn.addEventListener('click', () => {
  count++;
  display.textContent = count;
});

При каждом клике увеличиваем счётчик и обновляем текст на странице. Переменная count живёт снаружи обработчика — поэтому сохраняется между кликами.

✅ Пример 2: Валидация поля в реальном времени

const input = document.querySelector('#username');
const hint = document.querySelector('#hint');

input.addEventListener('input', (event) => {
  const value = event.target.value;

  if (value.length < 3) {
    hint.textContent = 'Слишком коротко — минимум 3 символа';
    hint.style.color = 'rgba(220, 50, 50, 1)';
  } else {
    hint.textContent = 'Отлично!';
    hint.style.color = 'rgba(0, 160, 100, 1)';
  }
});

Событие input срабатывает каждый раз, когда пользователь вводит или удаляет символ. event.target.value — текущее значение поля.

⌨️ Пример 3: Отслеживание клавиш

document.addEventListener('keydown', (event) => {
  console.log('Нажата клавиша:', event.key);

  if (event.key === 'Enter') {
    console.log('Нажали Enter!');
  }

  if (event.key === 'Escape') {
    closeModal(); // закрываем модалку
  }
});

event.key — строка с названием клавиши: 'Enter', 'Escape', 'a', 'ArrowUp' и т.д. Обработчик на document ловит нажатия клавиш в любом месте страницы.

✅ Итоги урока

  • Событие — сигнал о действии пользователя или браузера (click, input, keydown, submit, change, mouseover)
  • addEventListener('событие', колбэк) — основной способ подписаться на событие
  • Объект event содержит информацию: target, type, координаты и т.д.
  • event.preventDefault() — отменяет стандартное поведение браузера
  • event.stopPropagation() — останавливает всплытие события вверх по DOM
  • Всплытие — событие поднимается вверх от целевого элемента до document
  • Делегирование: один обработчик на родителя вместо обработчиков на каждый дочерний элемент

В следующем уроке научимся создавать и удалять элементы DOM — чтобы страница менялась прямо на глазах у пользователя. 🚀

События и обработчики

8 вопросов

Счётчик кликов

// Дан элемент counterDisplay (показывает число) и кнопка counterBtn. // Напишите код, который: // 1. Создаёт переменную count = 0 // 2. Добавляет обработчик 'click' на counterBtn // 3. При клике увеличивает count на 1 // 4. Обновляет textContent у counterDisplay let count = 0; const counterDisplay = null; const counterBtn = null; // Ваш код здесь

Делегирование событий

// Дан список taskList (
    ), содержащий
  • элементы. // Вместо того чтобы вешать обработчик на каждый
  • , // используйте делегирование: повесьте один обработчик 'click' // на taskList. При клике на
  • переключайте у него // класс 'done'. Используйте event.target и проверку tagName. const taskList = null; // Ваш код здесь