В предыдущем уроке была описана проблема, возникающая при добавлении новых элементов, и приведено ее решение. В данном уроке мы рассмотрим более удачный способ обойти проблему - делегирование событий. Давайте его разберем.
Как вы уже знаете, кликая на li
, мы
одновременно кликаем и на ul
. Это
возможно благодаря всплытию событий. Мы можем
использовать это для решения нашей задачи:
навесим событие не на каждую li
, а
на их родителя ul
:
list.addEventListener('click', function() {
});
Теперь в обработчике события this
будет указывать на элемент, к которому привязан
обработчик, а event.target
- на элемент,
в котором случилось событие:
list.addEventListener('click', function(event) {
console.log(this); // наш список
console.log(event.target); // пункт списка
});
Сделаем так, чтобы li
, на которой
случился клик, в конец добавлялся восклицательный
знак:
list.addEventListener('click', function(event) {
event.target.innerHTML = event.target.innerHTML + '!';
});
Повторите приведенное решение. Убедитесь,
что новые li
также будут реагировать
на клик.
Универсальное делегирование событий
Приведенный код рабочий, однако, не без недостатков. Давайте разберем эти недостатки и напишем более универсальное решение.
Недостаток нашего кода проявится в том случае,
когда внутри li
будут какие-то вложенные
теги. В нашем случае пусть это будут теги
i
:
<ul>
<li>item <i>italic</i> item</li>
<li>item <i>italic</i> item</li>
<li>item <i>italic</i> item</li>
<li>item <i>italic</i> item</li>
<li>item <i>italic</i> item</li>
</ul>
В этом случае нажатие на тег i
приведет
к добавлению восклицательного знака в конец
тега i
, а не тега li
, как
мы хотели бы - ведь в event.target
попадает именно тот тег, в котором случилось
событие.
Решить проблему можно с помощью метода closest
:
list.addEventListener('click', function(event) {
let li = event.target.closest('li');
if (li) {
li.innerHTML = li.innerHTML + '!';
}
});
Повторите приведенное решение.