Навязванне апрацоўшчыкаў на новыя элементы ў JavaScript

Няхай у нас ёсць спіс ul і кнопка:

html<ul>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
</ul>

<button>add</button>

Атрымаем нашы элементы ў адпаведныя зменныя:

javascriptlet button = document.querySelector('button');
let list   = document.querySelector('ul');
let items  = list.querySelectorAll('li');

Зробім так, каб па кліку на любую li ёй у канец дадаваўся клічнік:

javascriptfor (let item of items) {
  item.addEventListener('click', function() {
    this.textContent = this.textContent + '!';
  });
}

Давайце цяпер зробім так, каб па націсканні на кнопку ў канец спіса дадавалася новая li:

javascriptbutton.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'item';
  list.appendChild(item);
});

Мы, аднак, атрымаем праблему: клік на новы дададзены li не будзе прыводзіць да дадання клічніка ў канец. Справа ў тым, што мы дадаем апрацоўшчык кліка толькі на тыя li, якія існавалі першапачаткова, але не на новыя.

Выправім праблему, навесіўшы на новую li апрацоўшчык кліка:

javascriptbutton.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'item';
  
  item.addEventListener('click', function() { // апрацоўшчык кліка
    this.textContent = this.textContent + '!';
  });
  
  list.appendChild(item);
});

Аднак, цяпер код функцыі-апрацоўшчыка дублюецца ў двух месцах - для першапачаткова існуючых li і для новых. Выправім гэта, вынесшы яго ў асобную функцыю:

javascriptfunction handler() {
  this.textContent = this.textContent + '!';
}

Выкарыстаем нашую функцыю, каб пазбегнуць дублявання кода:

javascriptfor (let item of items) {
  item.addEventListener('click', handler);
}

button.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'item';
  
  item.addEventListener('click', handler);
  
  list.appendChild(item);
});

Задача ўвогуле вырашана і мы пазбеглі дублявання кода функцыі-апрацоўшчыка. Аднак, навязваць апрацоўшчыкі падзей нам усё роўна прыходзіцца ў двух месцах: і ў цыкле для існуючых li, і пры кліку на кнопку. У наступным уроке мы разбяром спосаб пазбавіцца ад гэтага незручнасці.