Kodokon kodokon.com

Работа с DOM: querySelector, обработчики событий

Выбирай элементы на странице, реагируй на клики и переходи к делегированию событий ради производительного кода.

9 мин · 3 вопросов

Открыть этот урок в Kodokon

DOM - это живое представление твоей HTML-страницы: работа с ним и есть то, чем JavaScript делает интерфейс интерактивным. Ключевой дуэт: выбрать элемент, а затем слушать, что с ним происходит. Начнём с небольшой исходной структуры.

HTML
<button id="save-btn" class="btn">Save</button>
<ul class="task-list">
  <li>Buy groceries</li>
  <li>Call the client</li>
</ul>
HTML-страница, с которой мы будем работать в следующих примерах.

querySelector принимает любой CSS-селектор (#id, .class, ul li, [data-id]) и возвращает первый подходящий элемент или null. querySelectorAll возвращает все подходящие элементы в виде NodeList, по которому можно пройтись через forEach.

JAVASCRIPT
const button = document.querySelector("#save-btn");
const firstTask = document.querySelector(".task-list li");
const tasks = document.querySelectorAll(".task-list li");

console.log(tasks.length); // 2
console.log(firstTask.textContent); // "Buy groceries"
Один элемент через querySelector, NodeList через querySelectorAll.

Чтобы реагировать на действие пользователя, addEventListener привязывает функцию к типу события: click, input, submit, keydown... Функция получает объект event, который описывает произошедшее. Дальше ты меняешь содержимое через textContent, а оформление - через classList.

JAVASCRIPT
const button = document.querySelector("#save-btn");

button.addEventListener("click", () => {
  button.textContent = "Saved!";
  button.classList.add("success");
});
По клику текст меняется и добавляется CSS-класс.

Хорошая профессиональная привычка: списку из 200 элементов не нужны 200 обработчиков. Повесь один обработчик на родителя и определяй элемент, по которому кликнули, через event.target. Это делегирование событий: оно работает даже для элементов, добавленных позже.

JAVASCRIPT
const list = document.querySelector(".task-list");

list.addEventListener("click", (event) => {
  const item = event.target.closest("li");
  if (item) {
    item.classList.toggle("done");
  }
});
Один обработчик на ul обслуживает клики по всем li.

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Что вернёт document.querySelector(".btn"), если класс btn есть у нескольких элементов?
    • Все подходящие элементы
    • Только первый подходящий элемент
    • Ошибку, потому что селектор неоднозначен
  2. Какова роль второго аргумента addEventListener?
    • Это функция, которая выполняется каждый раз при срабатывании события
    • Это задержка перед началом прослушивания
    • Это CSS-селектор целевого элемента
  3. В обработчике, повешенном на родителя, что представляет event.target?
    • Родителя, на котором висит обработчик
    • Тот самый элемент, на котором произошло событие
    • Окно браузера