Event-Handler für neue Elemente in JavaScript hinzufügen

Nehmen wir an, wir haben eine Liste ul und einen Button:

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

<button>add</button>

Wir holen unsere Elemente in die entsprechenden Variablen:

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

Sorgen wir dafür, dass bei einem Klick auf ein beliebiges li ein Ausrufezeichen an dessen Ende angehängt wird:

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

Lassen wir uns nun bei einem Klick auf den Button ein neues li am Ende der Liste hinzufügen:

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

Wir werden jedoch ein Problem feststellen: Ein Klick auf das neu hinzugefügte li führt nicht zum Anhängen eines Ausrufezeichens ans Ende. Der Grund dafür ist, dass wir den Click-Handler nur auf die li setzen, die anfänglich vorhanden waren, aber nicht auf die neuen.

Korrigieren wir das Problem, indem wir auf das neue li einen Click-Handler setzen:

javascriptbutton.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'item';
  
  item.addEventListener('click', function() { // Click-Handler
    this.textContent = this.textContent + '!';
  });
  
  list.appendChild(item);
});

Nun wird jedoch der Code der Handler-Funktion dupliziert - an zwei Stellen: für die anfänglich vorhandenen li und für die neuen. Beheben wir dies, indem wir ihn in eine separate Funktion auslagern:

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

Verwenden wir unsere Funktion, um Codeduplizierung zu vermeiden:

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

Die Aufgabe ist im Grunde gelöst und wir haben die Duplizierung des Codes der Handler-Funktion vermieden. Allerdings müssen wir die Event-Handler weiterhin an zwei Stellen setzen: sowohl in der Schleife für die vorhandenen li, als auch beim Klick auf den Button. In der nächsten Lektion werden wir eine Möglichkeit kennenlernen, um diese Unbequemlichkeit zu beseitigen.