Dodawanie obsługi zdarzeń do nowych elementów w JavaScript

Załóżmy, że mamy listę ul i przycisk:

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

<button>add</button>

Pobierzmy nasze elementy do odpowiednich zmiennych:

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

Sprawmy, aby po kliknięciu na dowolny li dodawał się na końcu wykrzyknik:

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

Zróbmy teraz tak, aby po naciśnięciu przycisku na końcu listy dodawał się nowy li:

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

Jednakże, napotkamy problem: kliknięcie na nowy dodany li nie spowoduje dodania wykrzyknika na końcu. Chodzi o to, że dodajemy obsługę kliknięcia tylko do tych li, które istniały początkowo, ale nie do nowych.

Naprawmy problem, dodając do nowego li obsługę kliknięcia:

javascriptbutton.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'item';
  
  item.addEventListener('click', function() { // obsługa kliknięcia
    this.textContent = this.textContent + '!';
  });
  
  list.appendChild(item);
});

Jednakże teraz kod funkcji obsługującej jest zduplikowany w dwóch miejscach - dla początkowo istniejących li i dla nowych. Naprawmy to, wynosząc go do osobnej funkcji:

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

Użyjmy naszej funkcji, aby uniknąć duplikacji kodu:

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);
});

Zadanie w zasadzie rozwiązane i uniknęliśmy duplikacji kodu funkcji obsługującej. Jednakże, dodawanie obsługi zdarzeń nadal musimy wykonywać w dwóch miejscach: zarówno w pętli dla istniejących li, jak i przy kliknięciu przycisku. W następnej lekcji omówimy sposób na pozbycie się tego niedogodności.