3 / 57
Как работают события в DOM?
Полный ответ
Базовая работа с событиями:
JavaScript
const button = document.getElementById("save");
// Добавить обработчик
button.addEventListener("click", function (event) {
console.log("Клик!", event.type); // "click"
console.log("Цель:", event.target); // элемент, на который кликнули
console.log("Координаты:", event.clientX, event.clientY);
});
// Удалить обработчик (нужна ссылка на ту же функцию)
function handleClick(event) {
console.log("Клик!");
}
button.addEventListener("click", handleClick);
button.removeEventListener("click", handleClick);
// ❌ Анонимную функцию нельзя удалить
button.addEventListener("click", () => console.log("Клик!"));
button.removeEventListener("click", () => console.log("Клик!")); // не удалится — другая функция
Объект события (Event):
JavaScript
element.addEventListener("click", function (event) {
// Основные свойства
event.type; // "click"
event.target; // элемент, на котором произошло событие
event.currentTarget; // элемент, на котором висит обработчик
event.timeStamp; // время события
// Управление поведением
event.preventDefault(); // отменить действие по умолчанию
event.stopPropagation(); // остановить дальнейшее распространение
event.stopImmediatePropagation(); // остановить + не вызывать другие обработчики на этом же элементе
});
preventDefault() — отмена стандартного поведения:
JavaScript
// Ссылка не перейдёт
document.querySelector("a").addEventListener("click", (e) => {
e.preventDefault();
console.log("Навигация отменена");
});
// Форма не отправится
document.querySelector("form").addEventListener("submit", (e) => {
e.preventDefault();
// Своя логика отправки
const data = new FormData(e.target);
fetch("/api/submit", { method: "POST", body: data });
});
// Запрет ввода нецифровых символов
input.addEventListener("keydown", (e) => {
if (!/\d/.test(e.key) && e.key !== "Backspace") {
e.preventDefault();
}
});
Типы событий:
JavaScript
// Мышь
element.addEventListener("click", handler); // клик
element.addEventListener("dblclick", handler); // двойной клик
element.addEventListener("mouseenter", handler); // курсор вошёл
element.addEventListener("mouseleave", handler); // курсор ушёл
// Клавиатура
element.addEventListener("keydown", handler); // клавиша нажата
element.addEventListener("keyup", handler); // клавиша отпущена
// Формы
element.addEventListener("input", handler); // ввод символа
element.addEventListener("change", handler); // значение изменилось (после blur)
element.addEventListener("submit", handler); // отправка формы
// Загрузка
window.addEventListener("load", handler); // страница и ресурсы загружены
window.addEventListener("DOMContentLoaded", handler); // DOM готов (быстрее load)
// Кастомное событие
const event = new CustomEvent("user:login", {
detail: { userId: 42, name: "Alice" },
});
document.dispatchEvent(event);
document.addEventListener("user:login", (e) => {
console.log("Пользователь вошёл:", e.detail.name);
});
Реальные кейсы
Третий аргумент addEventListener — options:
JavaScript
// once — обработчик сработает один раз и удалится
button.addEventListener("click", handler, { once: true });
// passive — обещание не вызывать preventDefault (для производительности скролла)
document.addEventListener("touchstart", handler, { passive: true });
// signal — отмена через AbortController
const controller = new AbortController();
button.addEventListener("click", handler, { signal: controller.signal });
// Позже: удалить обработчик
controller.abort(); // обработчик удалён
// AbortController удобнее, чем хранить ссылки на все функции
Типичные ошибки:
JavaScript
// ❌ this теряется в стрелочной функции
class App {
constructor() {
this.name = "MyApp"; // this внутри стрелки — это экземпляр App
button.addEventListener("click", () => {
console.log(this.name); // "MyApp" — ок
}); // this в обычной функции — это элемент button
button.addEventListener("click", function () {
console.log(this); // <button> — не экземпляр App!
});
}
}
Резюме
События — основа интерактивности в браузере. addEventListener добавляет обработчики, объект Event содержит информацию о произошедшем, preventDefault() отменяет стандартное поведение. Используй once, passive и AbortController для чистого и производительного кода.