การติดตั้งตัวจัดการเหตุการณ์บนองค์ประกอบใหม่ใน 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 ที่มีอยู่ และเมื่อคลิกที่ปุ่ม ในบทเรียนหน้าเราจะพูดถึงวิธีกำจัดความไม่สะดวกนี้