Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> ซอฟต์แวร์ >> เบราว์เซอร์

ควบคุมพฤติกรรมเบราว์เซอร์: Mastering event.preventDefault() และ event.stopPropagation()

เบราว์เซอร์มีการโต้ตอบและพฤติกรรม Default สำหรับ Event ต่างๆ

ตัวอย่าง: User กดปุ่ม "Submit" บน Form -> Form ส่งข้อมูลไป URL โดย Default

คลิก Child Element -> Click Event เกิดบน Parent ด้วย (เพราะ Child อยู่ใน Container)

บางกรณีอยาก Override Default นี้ บทความนี้สอน event.preventDefault() และ event.stopPropagation() ยกเลิก Default Actions ในเบราว์เซอร์

event.preventDefault()

ป้องกัน Default Actions ที่เบราว์เซอร์ทำเมื่อ Event ถูก Trigger

Override Default Form Submission

Submit Form (กดปุ่ม Submit) -> Default: ส่ง Form Data ไป URL ตาม action และ method (get, post) หากไม่ระบุ: URL = Current Page, Method = GET

โค้ด HTML:

<form>
  <input name="email" />
  <input name="password" />
  <input type="submit" />
</form>

Submit ด้วย "dillion" และ "password" -> GET Request ไป 127.0.0.1:5500/index.html

ควบคุมพฤติกรรมเบราว์เซอร์: Mastering event.preventDefault() และ event.stopPropagation() ควบคุมพฤติกรรมเบราว์เซอร์: Mastering event.preventDefault() และ event.stopPropagation()

แต่มันมักต้อง: Validate, Check, Process, Config Headers ก่อนส่ง Request

วิธีป้องกัน Default:

<form id='form'> ... </form>
const form = document.getElementById('form')
form.addEventListener('submit', (event) => {
  event.preventDefault()
  // process data และส่ง request เอง
})

ตอนนี้การ Submit Form อยู่ในมือคุณ

คลิก Link (<a href>) -> Default: Navigate ไป URL นั้น

อยาก Intercept ทำอะไรก่อน Navigate?เช่น Check Permission

<a id="link" href="https://google.com">Google</a>
const link = document.getElementById("link")
link.addEventListener("click", event => {
  event.preventDefault()
  // do something แล้ว navigate เอง
})

ทดสอบ: คลิก "Google" -> ไม่ Navigate เพราะ Prevent Default แล้ว ต้อง Handle Navigation เอง

event.stopPropagation()

Propagation = การแพร่กระจาย Event stopPropagation หยุดการแพร่กระจายเมื่อ Event Trigger บน Element

ใน JS: Trigger Event บน Element -> Event Bubble ขึ้นไป Parents/Ancestors (Child อยู่ใน Container -> Parent รับ Event)

คลิก Child ของ Element

HTML:

<div>
  <button>Click me</button>
</div>

คลิก Button -> คลิก Div ด้วย (Button ใน Container) Event Propagate Button -> Div -> Grandparents -> Root

ทดสอบโค้ด:

<div id="div">
  <button id="button">Click me</button>
</div>
const div = document.getElementById('div')
const button = document.getElementById('button')
button.addEventListener('click', () => console.log('button clicked'))
div.addEventListener('click', () => console.log('div container clicked'))

คลิก Button -> Console แสดงทั้ง 2 บรรทัด (Div ก็รับ Event)

ควบคุมพฤติกรรมเบราว์เซอร์: Mastering event.preventDefault() และ event.stopPropagation()

ตัวอย่างจริง: Gmail New Message Popup

ควบคุมพฤติกรรมเบราว์เซอร์: Mastering event.preventDefault() และ event.stopPropagation()

Top Bar: 3 ปุ่ม (Minimize, Fullscreen, Close) + ข้อความ "New Message" มี Click Handler -> Minimize Popup

ควบคุมพฤติกรรมเบราว์เซอร์: Mastering event.preventDefault() และ event.stopPropagation()

ปัญหา: กดปุ่ม Close -> Event Propagate ไป Top Bar -> Minimize ด้วย (ไม่ต้องการ!)

แก้ด้วย stopPropagation() บนปุ่ม:

<div id='top-bar'>
  <!-- Message -->
  <!-- Buttons -->
</div>
const topBar = document.getElementById('top-bar')
const closeButton = document.getElementById('close-btn')
topBar.addEventListener('click', () => { /* minimize/maximize */ })
closeButton.addEventListener('click', (event) => {
  event.stopPropagation()
  // close popup
})

ตอนนี้ Top Bar รับ Event เฉพาะคลิกโดยตรงเท่านั้น

สรุป

ความแตกต่าง:

  • event.preventDefault() - ป้องกัน Default Action ของ **Browser** (Submit Form, Navigate Link)
  • event.stopPropagation() - ป้องกัน Default Behavior ของ **Event** (Bubbling ขึ้น Tree)

Default Actions/Behaviors ไม่ใช่ Bug ไม่ต้องกังวลตอนเขียนโค้ด แต่บาง Scenario ต้อง Override ตามตัวอย่างข้างต้น