หัวข้อ 3: Event Handling, Bubbling และ Capturing

คำจำกัดความ

Event คือเหตุการณ์ที่เกิดขึ้นบนหน้าเว็บ เช่น click, input, submit, keydown ส่วน Event Handling คือการเขียนโค้ดเพื่อรับมือกับเหตุการณ์เหล่านั้น

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#458588", "primaryTextColor": "#fbf1c7", "primaryBorderColor": "#fabd2f", "lineColor": "#a89984", "secondaryColor": "#b8bb26", "tertiaryColor": "#d3869b", "background": "#282828", "mainBkg": "#3c3836", "textColor": "#ebdbb2"}}}%%
flowchart TD
  A["Root
Document"] --> B["Parent
Container"] B --> C["Child
Button"] A -. "Capturing
บนลงล่าง" .-> C C -. "Bubbling
ล่างขึ้นบน" .-> A

addEventListener

<button id="saveButton">บันทึก</button>

<script>
  const button = document.getElementById("saveButton");

  button.addEventListener("click", event => {
    // event.type คือชื่อ event
    console.log(event.type); // click
    console.log("บันทึกข้อมูลแล้ว");
  });
</script>

Event Object

Property/Method ความหมาย
event.target element ที่เป็นต้นเหตุจริง
event.currentTarget element ที่ listener ผูกอยู่
event.type ชื่อ event
preventDefault() ยับยั้งพฤติกรรม default
stopPropagation() หยุดการ bubble/capture ต่อ

preventDefault()

const form = document.querySelector("form");

form.addEventListener("submit", event => {
  // ป้องกัน browser reload หน้า
  event.preventDefault();
  console.log("ตรวจสอบฟอร์มด้วย JavaScript ก่อนส่ง");
});

stopPropagation()

const parent = document.querySelector(".parent");
const child = document.querySelector(".child");

parent.addEventListener("click", () => console.log("parent clicked"));

child.addEventListener("click", event => {
  // หยุดไม่ให้ event ไหลขึ้น parent
  event.stopPropagation();
  console.log("child clicked");
});

Event Bubbling และ Capturing

document.addEventListener("click", () => {
  console.log("capturing phase");
}, true); // true = capturing

Event Delegation

Event Delegation คือการผูก event ที่ parent เพียงจุดเดียว แล้วตรวจ event.target เพื่อจัดการ child

<ul id="menu">
  <li data-page="home">หน้าแรก</li>
  <li data-page="course">รายวิชา</li>
  <li data-page="contact">ติดต่อ</li>
</ul>

<script>
  const menu = document.getElementById("menu");

  menu.addEventListener("click", event => {
    // ตรวจว่าคลิก li จริงหรือไม่
    if (event.target.matches("li")) {
      console.log(`เปิดหน้า: ${event.target.dataset.page}`);
    }
  });
</script>

สมการลดจำนวน Listener ด้วย Delegation

saved = n - 1

โดยที่ saved คือจำนวน listener ที่ลดได้, n คือจำนวน child element, และ 1 คือ listener เดียวบน parent

แบบทดสอบหลังเรียน

  1. event.target และ event.currentTarget ต่างกันอย่างไร
  2. preventDefault() เหมาะกับ event ใด
  3. Bubbling คืออะไร
  4. Capturing ใช้งานอย่างไรใน addEventListener
  5. Event Delegation มีข้อดีอย่างไร

กลับสัปดาห์ที่ 5