0Pricing
JavaScript Academy · Урок

Динамические списки с делегированием

Управляйте событиями элементов, добавленных во время выполнения.

«Динамические списки с делегированием» — бесплатный урок JavaScript Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения JavaScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс JavaScript Academy содержит 4 уроков всего.

Проблема динамических элементов

Если прикреплять обработчики непосредственно к элементам, у любого элемента, добавленного в DOM после настройки, обработчика не будет. Делегирование решает эту проблему, потому что обработчик родительского элемента также перехватывает события будущих дочерних элементов.

Прямые обработчики не работают

Здесь обработчик добавляется к существующим элементам. Новый добавленный элемент ничего не получает и остаётся неактивным.

document.querySelectorAll(".item").forEach((el) =>
  el.addEventListener("click", handle)
);
list.appendChild(newItem); // newItem has NO handler

Делегирование работает автоматически

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

list.addEventListener("click", (e) => {
  const item = e.target.closest(".item");
  if (item) console.log("Clicked", item.dataset.id);
});
list.appendChild(newItem); // works immediately

Добавление элементов

Создавайте новые элементы и добавляйте их. Поскольку родительский элемент уже использует делегирование, они становятся интерактивными сразу после появления.

function addItem(text) {
  const li = document.createElement("li");
  li.className = "item";
  li.textContent = text;
  list.appendChild(li);
}

Удаление элементов

Удаление также выполняется просто. Обработчик с делегированием может обнаружить кнопку удаления внутри строки и удалить строку.

list.addEventListener("click", (e) => {
  if (e.target.matches(".delete-btn")) {
    e.target.closest(".item").remove();
  }
});

Различение поддействий

В строке может быть несколько интерактивных частей. Используйте matches() или closest(), чтобы определить, на какой из них произошёл щелчок, а затем выполните нужную ветвь.

list.addEventListener("click", (e) => {
  if (e.target.matches(".edit-btn")) edit(e);
  else if (e.target.matches(".delete-btn")) del(e);
});

Отрисовка из данных

Распространённый шаблон: хранить состояние в массиве, отрисовывать строки на его основе и делегировать обработку щелчков. Повторная отрисовка заменяет дочерние элементы, но единственный обработчик родительского элемента продолжает работать без изменений.

function render(items) {
  list.innerHTML = items
    .map((i) => "<li class=\"item\" data-id=\"" + i.id + "\">" + i.name + "</li>")
    .join("");
}

Без сложностей с очисткой

При использовании обработчиков на отдельных элементах перед удалением узлов нужно не забыть вызвать removeEventListener, чтобы избежать утечек. Делегирование снимает эту обязанность: удаление дочернего элемента не оставляет обработчик без владельца.

Переключение классов

Делегирование хорошо сочетается с переключением классов для состояний выбора. Обработчик находит строку и переключает класс.

list.addEventListener("click", (e) => {
  const row = e.target.closest(".item");
  if (row) row.classList.toggle("selected");
});

Чтение стабильного идентификатора

Поскольку узлы DOM заменяются при повторной отрисовке, никогда не храните ссылки на них. Храните стабильный идентификатор в data-id и ищите данные в своей модели по этому идентификатору внутри обработчика.

const id = e.target.closest(".item").dataset.id;
const record = state.find((r) => r.id === id);

События ввода тоже

Делегирование не ограничивается щелчками. Вы можете таким же способом делегировать события input или change для динамически добавленных полей формы.

form.addEventListener("input", (e) => {
  if (e.target.matches(".qty")) recalc(e.target);
});

Быстрая проверка

Динамические списки и делегирование.

Итоги

Делегирование особенно полезно для динамических списков: один обработчик родительского элемента обслуживает текущие и будущие дочерние элементы, сохраняется после повторной отрисовки и не требует очистки отдельных узлов. Используйте matches() и closest(), чтобы выбирать ветвь по поддействию, и храните стабильные идентификаторы в data-*, чтобы обработчики могли находить Вашу модель данных.

Часто задаваемые вопросы

Урок «Динамические списки с делегированием» бесплатный?

Да — полный текст урока «Динамические списки с делегированием» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс JavaScript Academy, подпишись на CoddyKit PRO. Курс JavaScript Academy содержит 4 уроков всего.

Чему я научусь в уроке «Динамические списки с делегированием»?

Управляйте событиями элементов, добавленных во время выполнения. Ты практикуешь JavaScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать JavaScript Academy?

Предыдущий опыт не требуется. JavaScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Динамические списки с делегированием»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке JavaScript Academy?

Да. Каждый урок JavaScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Фазы перехвата и всплытия
  2. Шаблон делегирования событий
  3. Динамические списки с делегированием
  4. Пользовательские события
← Назад к JavaScript Academy