Введение

Это пост из моей серии Вопросы для собеседования по интерфейсу JavaScript, где я даю ответы и примеры на распространенные вопросы интервью по интерфейсу JavaScript. Если вам понравился этот пост, подписывайтесь на меня в Medium, Github или Twitter!

Примечание: большинство вопросов для интервью я получаю из этого отличного справочника, но время от времени я могу отклоняться!

Вопрос этого поста: что такое делегирование событий?

Делегирование события добавляет event listener к родительскому элементу в DOM, а не прикрепляет его к каждому дочернему элементу. Чтобы понять, почему мы хотели бы это сделать, давайте возьмем общий пример: элементы в списке. Вот наш HTML:

<ul id="my-list">
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>

Допустим, мы хотим console.log просмотреть содержимое элемента списка при нажатии на него. Без делегирования событий мы можем написать следующий javascript:

let listItems = document.querySelectorAll("#my-list li");
for (let i = 0; i < listItems.length; i++) {
  listItems[i].addEventListener("click", e => {
    console.log(e.target.innerHTML);
  });
}

Это сработает, но допустим, нам нужно динамически добавить еще один элемент списка. Наш javascript становится примерно таким:

let listItems = document.querySelectorAll("#my-list li");
for (let i = 0; i < listItems.length; i++) {
  listItems[i].addEventListener("click", e => {
    console.log(e.target.innerHTML);
  });
}
let list = document.querySelector("#my-list");
let newItem = document.createElement("li");
newItem.innerHTML = "Four";
list.appendChild(newItem);

Но теперь, если мы попытаемся нажать на этот четвертый пункт, в консоли ничего не логируется (см. это во всей своей несостоятельности здесь). Это связано с тем, что четвертого элемента не существовало, когда event listeners были добавлены к другим элементам списка. Технически мы могли добавлять новый event listener каждый раз, когда добавляем новый элемент списка, но это громоздко. Вместо этого мы можем использовать делегирование событий!

Чтобы использовать event delegation, нам просто нужно понять, что событие клика всплывает от элементов li к элементам ul. элемент. Мы можем прикрепить щелчок event listener к родительскому элементу ul и выполнить действие console.log, если событием щелчка target является li. Наш javascript становится таким:

let list = document.querySelector("#my-list");
list.addEventListener("click", e => {
  if (e.target && e.target.nodeName == "LI") {
    console.log(e.target.innerHTML);
  }
});
let newItem = document.createElement("li");
newItem.innerHTML = "Four";
list.appendChild(newItem);

Как вы можете видеть в этой скрипте, желаемое console.log отлично работает с четвертым элементом без необходимости вручную добавлять дополнительные event listeners.