Capstone: JS + DOM click เปลี่ยนหน้าจริง
เอา JS จาก stage 1 มาต่อกับ HTML+CSS ครั้งแรก สร้าง theme toggle ทำงานจริง เรียนรู้ querySelector, addEventListener, classList 3 API หลักของ DOM
ถึงบทสุดท้ายของ topic HTML + CSS แล้ว ที่ผ่านมาเราเรียนกันไปว่า:
- HTML คือโครงสร้างที่ browser แปลงเป็นต้นไม้ (บท 1)
- CSS คือภาษาบอก style มี selector กับ specificity (บท 2)
- ทุก element คือกล่อง 4 ชั้น (บท 3)
- Flexbox จัด layout 80% ของเว็บ (บท 4)
- Typography กับ color ทำให้ไม่น่าเกลียด (บท 5)
- Responsive ทำเว็บเดียวใช้ทุกจอ (บท 6)
ทั้งหมดนี้ยังมีสิ่งหนึ่งที่ขาดอยู่คือ interactivity เว็บที่เขียนมายังนิ่งๆ ไม่มี click ไม่มี toggle ไม่มี animation
บทนี้คือจุดที่ JS ที่เรียนมา 10 บทใน stage 1 เพิ่งได้ใช้ออกจาก console เป็นครั้งแรก เอา JS มาต่อกับ DOM แล้วเว็บของเราจะ click ได้ กด toggle ได้ interactive ได้
DOM คือตัวเชื่อม HTML กับ JS
จำบท 1 ได้ไหม ที่บอกว่า HTML คือต้นไม้ (DOM) ชื่อเต็มคือ Document Object Model ที่ browser สร้างจาก HTML ของเรา
JS สามารถเข้าถึงต้นไม้ตัวนี้ผ่าน object ชื่อ document เราสั่ง document ให้:
- หา element ที่ต้องการ (select)
- ฟังเหตุการณ์เช่น click (listen)
- แก้ไขหน้าเว็บ เช่น เพิ่ม class หรือเปลี่ยนข้อความ (mutate)
3 เรื่องนี้ครอบคลุม 80% ของงาน JS ที่ต่อกับหน้าเว็บ
ประกอบทีละ layer: HTML → CSS → JS
ลองเล่นกับ widget นี้ดู จะได้เห็นว่า 3 ภาษาทำงานต่อกันยังไง กดปุ่ม "เพิ่ม layer ถัดไป" เพื่อดูแต่ละขั้น แล้วขั้นสุดท้ายกดปุ่มจริงในช่อง preview ได้เลย
<body>
<h1>Vibe Coding</h1>
<p>เว็บแรกที่ทำเองทั้งหมด HTML + CSS + JS</p>
<button id="theme-toggle">🌙 สลับธีม</button>
</body>สังเกตว่าจริงๆ JS ที่ใช้มีแค่ 3 บรรทัด:
const button = document.querySelector('#theme-toggle');
button.addEventListener('click', () => {
document.body.classList.toggle('dark');
});แค่ 3 บรรทัดนี้ครอบคลุม API สำคัญที่สุดของ DOM ทั้งหมด มาดูทีละตัวว่าทำอะไร
querySelector เลือก element ด้วย CSS selector
document.querySelector(selector) รับ string selector (syntax เดียวกับ CSS ที่เรียนในบท 2) แล้วคืน element แรกที่เข้าเงื่อนไข
document.querySelector('#theme-toggle') // หา id
document.querySelector('.btn') // หา class แรกที่เจอ
document.querySelector('nav a') // descendant selector
document.querySelectorAll('.card') // ได้ NodeList มาทั้งหมดจำบท 2 ได้ใช่ไหม ที่เราเรียน selector สำหรับ CSS วันนี้ syntax เดียวกันเลย ใช้กับ JS ได้ทันที
addEventListener ฟังเหตุการณ์
element.addEventListener(eventName, handler) บอก element ว่า "ตอน event นี้เกิด ให้เรียก function นี้"
button.addEventListener('click', () => {
// function นี้ทำงานตอน click
console.log('clicked!');
});Event ที่เจอบ่อย:
clickตอนคลิก (mouse หรือ touch ก็ได้)inputตอน user พิมพ์ใน input fieldsubmitตอน form submitmouseenter/mouseleaveตอน hoverkeydown/keyupตอนกดปุ่ม keyboard
classList จัดการ class ของ element
element.classList คือ object ที่จัดการ class ของ element มี 4 method หลัก:
add('foo')เพิ่ม class ถ้ามีอยู่แล้วไม่เกิดอะไรremove('foo')ลบ class ถ้าไม่มีอยู่ก็เฉยๆtoggle('foo')มีอยู่ลบออก ไม่มีเพิ่มเข้าไปcontains('foo')เช็คว่ามี class นี้ไหม คืน true หรือ false
ลองเล่นดูว่าแต่ละ method ทำงานยังไง:
.darkพื้นดำ ตัวอักษรขาว.roundedมุมโค้ง.bigขนาดใหญ่.shadowเงาลึก<script> วางตรงไหน
pain point ที่มือใหม่เจอเวลาเขียน JS กับ HTML คือ: ใส่ <script> ตรงไหนดี
มี 3 ตำแหน่งที่วางได้:
<!-- วิธี 1: ใน <head> ตรงๆ (ไม่แนะนำ) -->
<head>
<script src="app.js"></script>
</head>
<!-- วิธี 2: ท้าย <body> (เก่าแต่ใช้ได้) -->
<body>
<!-- content -->
<script src="app.js"></script>
</body>
<!-- วิธี 3: <head> + defer (ใช้จริง) -->
<head>
<script src="app.js" defer></script>
</head>ปัญหาของวิธี 1 คือ JS ทำงานก่อน DOM โหลดเสร็จ ทำให้ querySelector หาไม่เจอเพราะ element ยังไม่มีในหน้า
วิธี 2 แก้ปัญหาได้ แต่ JS โหลดช้า เพราะรอทุกอย่างใน body ก่อน
วิธี 3 defer บอก browser ว่า "โหลด script ไปพร้อมกับ HTML แต่รอให้ HTML parse เสร็จก่อนค่อย execute" เร็วและปลอดภัยที่สุด
Pattern ที่ใช้ทุกวัน
Theme toggle (อย่างที่เพิ่งเล่น)
document.querySelector('#theme')
.addEventListener('click', () => {
document.body.classList.toggle('dark');
});Dropdown menu เปิดปิด
const menu = document.querySelector('.menu');
document.querySelector('.menu-btn')
.addEventListener('click', () => {
menu.classList.toggle('open');
});Form validation ง่ายๆ
const input = document.querySelector('#email');
input.addEventListener('input', () => {
const valid = input.value.includes('@');
input.classList.toggle('error', !valid);
});Modal เปิดปิดทั้งหน้า
const modal = document.querySelector('#modal');
document.querySelector('#open-btn')
.addEventListener('click', () => modal.classList.add('visible'));
document.querySelector('#close-btn')
.addEventListener('click', () => modal.classList.remove('visible'));สรุป
- DOM คือต้นไม้ HTML ที่ JS เข้าถึงได้ผ่าน
document - querySelector รับ CSS selector แล้วคืน element (syntax เดียวกับ CSS)
- addEventListener ฟัง event เช่น click, input, submit
- classList มี 4 method: add, remove, toggle, contains
- Pattern ที่ดี คือ CSS จัดหน้าตา JS แค่ toggle class ไม่แก้ style ตรงๆ
<script defer>ใน head คือวิธีที่ดีที่สุดสำหรับ script ที่แก้ DOM
จบ topic HTML + CSS แล้ว
ถึงจุดนี้คุณเขียนเว็บของตัวเองได้แล้วจริงๆ HTML วางโครงสร้าง CSS จัดหน้าตา JS ทำให้ interactive ทั้ง 3 อย่างนี้เป็นพื้นฐานของทุกเว็บบนโลก ไม่ว่าจะเว็บเล็กๆ ของ dev คนเดียว หรือ Facebook YouTube Netflix ก็ใช้ 3 ภาษาเดียวกันนี้
ลองเอาความรู้ไปทำ mini project ดู เช่น:
- Portfolio ของตัวเองสำหรับใส่ resume
- Landing page สำหรับ project ของตัวเอง
- To-do list app ใช้ class toggle กับ list
- Calculator หน้าตาดีๆ ที่ใช้ flexbox + grid
เว็บที่ทำเสร็จแล้ว เอาขึ้น GitHub Pages หรือ Vercel ฟรีๆ ได้เลย (ต้องใช้ Git ที่เรียนใน stage 3) แล้วใส่ลิงก์ใน CV หรือ LinkedIn ให้คนเห็นงานของตัวเอง
เก่งขึ้นมาเยอะแล้วครับ เดินทางจากเขียน HTML <h1> ตัวเดียวไม่ได้ มาจนเขียนเว็บ interactive เป็นแล้ว เส้นทาง vibe coder ยังอีกไกล แต่ 7 บทนี้คือรากที่แน่นแล้ว