Вивчай

Події — частина 1

JavaScript події — палець натискає дверний дзвінок очікуючи реакціюJavaScript події — палець натискає дверний дзвінок очікуючи реакцію

У попередніх уроках ми навчилися знаходити елементи та змінювати DOM. Але поки наш код виконується одразу при завантаженні сторінки. А як зробити так, щоб щось відбувалося при кліку на кнопку або при наведенні миші? Для цього існують події.


Що таке подія?

Подія — це сигнал від браузера, що щось сталося. Користувач клікнув, навів мишу, натиснув клавішу, прокрутив сторінку — кожна з цих дій створює подію.

JavaScript може слухати події та виконувати код у відповідь. Функцію, яка виконується при події, називають обробником (handler).


addEventListener — додавання обробника

Основний спосіб реагувати на події:

const button = document.querySelector(".btn");

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

Синтаксис: element.addEventListener(типПодії, функціяОбробник)

З arrow function (зручніше):

button.addEventListener("click", () => {
  console.log("Клік!");
});
Порада

Пам'ятаєш callbacks з Block 4? Другий аргумент addEventListener — це саме callback-функція. Браузер викличе її, коли подія відбудеться.

Кілька обробників на одну подію

На один елемент можна повісити скільки завгодно обробників:

const btn = document.querySelector(".btn");

btn.addEventListener("click", () => {
  console.log("Обробник 1");
});

btn.addEventListener("click", () => {
  console.log("Обробник 2");
});

// При кліку виведе обидва повідомлення

Основні типи подій миші

ПодіяКоли спрацьовує
clickКлік лівою кнопкою миші
dblclickПодвійний клік
mouseenterКурсор заходить на елемент
mouseleaveКурсор покидає елемент
mouseoverКурсор заходить на елемент або його дочірній
mouseoutКурсор покидає елемент або його дочірній
mousedownКнопку миші натиснули (до відпускання)
mouseupКнопку миші відпустили
const card = document.querySelector(".card");

card.addEventListener("mouseenter", () => {
  card.classList.add("card--hover");
  console.log("Мишка на картці");
});

card.addEventListener("mouseleave", () => {
  card.classList.remove("card--hover");
  console.log("Мишка пішла з картки");
});
Інфо

Яка різниця між mouseenter/mouseleave та mouseover/mouseout? Перша пара не спрацьовує при переході між дочірніми елементами. Зазвичай mouseenter/mouseleave зручніші, бо не створюють зайвих спрацювань.


Об'єкт event

Коли подія відбувається, браузер створює об'єкт події з детальною інформацією. Він автоматично передається першим аргументом в обробник:

const button = document.querySelector(".btn");

button.addEventListener("click", (event) => {
  console.log(event.type);     // "click"
  console.log(event.target);   // елемент, на якому клікнули
  console.log(event.clientX);  // X-координата кліку
  console.log(event.clientY);  // Y-координата кліку
});

Найважливіші властивості event

ВластивістьОпис
event.typeТип події ("click", "mouseenter" тощо)
event.targetЕлемент, на якому реально сталася подія
event.currentTargetЕлемент, на якому висить обробник
event.clientX / clientYКоординати миші відносно вікна
event.pageX / pageYКоординати миші відносно сторінки
document.addEventListener("click", (event) => {
  console.log("Клік на:", event.target.tagName);
  console.log("Координати:", event.clientX, event.clientY);
});

event.target — де саме клікнули

Це одна з найкорисніших властивостей. event.target вказує на конкретний елемент, на якому сталася подія:

const nav = document.querySelector("nav");

nav.addEventListener("click", (event) => {
  // Перевіряємо, чи клікнули саме на посилання
  if (event.target.tagName === "A") {
    console.log("Натиснули посилання:", event.target.textContent);
  }
});

removeEventListener — видалення обробника

Щоб видалити обробник, потрібно передати ту саму функцію:

// Зберігаємо функцію в змінну
const handleClick = () => {
  console.log("Клік!");
};

const btn = document.querySelector(".btn");

btn.addEventListener("click", handleClick);

// Пізніше — видаляємо
btn.removeEventListener("click", handleClick);
Увага

Анонімну функцію неможливо видалити! Ось цей код не працює:

btn.addEventListener("click", () => console.log("Клік"));
btn.removeEventListener("click", () => console.log("Клік")); // не видалить!

Це дві різні функції, хоча виглядають однаково. Щоб мати змогу видалити обробник, завжди зберігай функцію в змінну.


Практика: лічильник кліків

<div class="counter">
  <button class="counter__btn counter__btn--minus">-</button>
  <span class="counter__value">0</span>
  <button class="counter__btn counter__btn--plus">+</button>
</div>
const minusBtn = document.querySelector(".counter__btn--minus");
const plusBtn = document.querySelector(".counter__btn--plus");
const valueDisplay = document.querySelector(".counter__value");

let count = 0;

plusBtn.addEventListener("click", () => {
  count++;
  valueDisplay.textContent = count;
});

minusBtn.addEventListener("click", () => {
  count--;
  valueDisplay.textContent = count;
});

Практика: підсвічування елементів

const items = document.querySelectorAll(".gallery-item");

items.forEach((item) => {
  item.addEventListener("mouseenter", (event) => {
    event.target.classList.add("gallery-item--active");
  });

  item.addEventListener("mouseleave", (event) => {
    event.target.classList.remove("gallery-item--active");
  });
});

Старий спосіб: onclick (не рекомендується)

Існує старіший спосіб — через атрибут або властивість:

// Через властивість — дозволяє тільки один обробник
const btn = document.querySelector(".btn");
btn.onclick = () => console.log("Клік");

// Другий присвоєний обробник замінить перший!
btn.onclick = () => console.log("Інший клік"); // попередній загублено
<!-- Через HTML-атрибут — найгірший варіант -->
<button onclick="alert('Клік!')">Натисни</button>
Увага

Завжди використовуй addEventListener. Він дозволяє додавати кілька обробників, легко видаляти їх, і тримає JavaScript окремо від HTML.


Підсумок

  • Подія — сигнал від браузера, що щось сталося (клік, наведення тощо)
  • addEventListener(type, handler) — додає обробник події
  • event.target — елемент, на якому реально сталася подія
  • event.type — тип події (click, mouseenter тощо)
  • removeEventListener — видаляє обробник (потрібна та сама функція)
  • mouseenter/mouseleave — зручніші за mouseover/mouseout
  • Завжди використовуй addEventListener замість onclick

Що далі?

У наступному уроці заглибимося в події: bubbling, capturing, event delegation та keyboard events.

Інфо

Корисні посилання: