Tilføjelse af event handlers til nye elementer i JavaScript

Lad os sige, at vi har en liste ul og en knap:

html<ul>
  <li>element</li>
  <li>element</li>
  <li>element</li>
  <li>element</li>
  <li>element</li>
</ul>

<button>tilføj</button>

Lad os hente vores elementer ind i de tilsvarende variable:

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

Lad os gøre det, så der ved et klik på enhver li tilføjes et udråbstegn til slutningen:

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

Lad os nu gøre det, så der ved et klik på knappen tilføjes en ny li til slutningen af listen:

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

Vi vil dog støde på et problem: et klik på den nyligt tilføjede li vil ikke føre til tilføjelsen af et udråbstegn i slutningen. Grunden er, at vi tilføjer klik-handleren kun til de li, som eksisterede oprindeligt, men ikke til de nye.

Lad os rette problemet ved at tilføje en klik-handler til den nye li:

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

Nu bliver koden for handler-funktionen dog duplikeret på to steder - for de oprindeligt eksisterende li og for de nye. Lad os rette dette ved at flytte den til en separat funktion:

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

Lad os bruge vores funktion for at undgå kodeduplicering:

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

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

Opgaven er egentlig løst, og vi har undgået duplicering af handler-funktionens kode. Vi er dog stadig nødt til at tilføje event handlers på to steder: både i løkken for de eksisterende li og ved klik på knappen. I den næste lektion vil vi se på en metode til at undgå denne ubehagelighed.