บทก่อนหน้าเน้นการสร้างโครงสร้างและหน้าตาด้วย HTML5 และ CSS3 ส่วนบทนี้จะเพิ่มความสามารถด้านพฤติกรรมของหน้าเว็บด้วย JavaScript เช่น คลิกปุ่มแล้วเปลี่ยนข้อมูล ตรวจสอบฟอร์ม โหลดรายการจาก API และอัปเดตหน้าเว็บโดยไม่ต้อง reload
คำสำคัญของบทเรียน
let, const, arrow function, template literal และ moduleJavaScript ทำหน้าที่เชื่อมระหว่างโครงสร้างหน้าเว็บ ข้อมูล และการกระทำของผู้ใช้ เมื่อผู้ใช้คลิกปุ่ม พิมพ์ข้อความ ส่งฟอร์ม หรือเลือกตัวกรอง JavaScript จะรับ event แล้วสั่งให้หน้าเว็บอัปเดตเฉพาะส่วนที่เกี่ยวข้อง
%%{init: {'theme': 'base', 'themeVariables': {
'background': '#282828',
'primaryColor': '#3c3836',
'primaryTextColor': '#fbf1c7',
'primaryBorderColor': '#fabd2f',
'lineColor': '#83a598',
'secondaryColor': '#504945',
'tertiaryColor': '#665c54',
'fontFamily': 'Arial'
}}}%%
flowchart LR
A[User Action
การกระทำของผู้ใช้] --> B[Event Listener
ตัวรับเหตุการณ์]
B --> C[JavaScript Logic
ตรรกะของโปรแกรม]
C --> D[DOM Update
อัปเดตหน้าเว็บ]
C --> E[Fetch API
ดึงข้อมูลจาก API]
E --> D
| งาน | ตัวอย่าง |
|---|---|
| เปลี่ยนเนื้อหา | แสดงข้อความต้อนรับหลังผู้ใช้กรอกชื่อ |
| ตรวจสอบฟอร์ม | ตรวจว่าอีเมลถูกต้องก่อนส่ง |
| จัดการรายการ | เพิ่ม ลบ ค้นหา หรือกรองข้อมูล |
| ติดต่อ API | โหลดสินค้า ข่าว หรือข้อมูลผู้ใช้จาก server |
| ปรับประสบการณ์ผู้ใช้ | แสดง loading, error message หรือ notification |
let, const และ varVariable คือชื่อที่ใช้เก็บข้อมูลเพื่อนำไปใช้ต่อในโปรแกรม ใน JavaScript สมัยใหม่ควรใช้ const เป็นค่าเริ่มต้น และใช้ let เมื่อต้องเปลี่ยนค่า ส่วน var เป็นรูปแบบเก่าที่ควรหลีกเลี่ยงในงานใหม่ เพราะ scope ทำให้สับสนได้ง่าย
| คำสั่ง | ใช้เมื่อ | เปลี่ยนค่าได้หรือไม่ | ขอบเขต |
|---|---|---|---|
const |
ค่าที่ไม่ต้องกำหนดใหม่ | ไม่ได้ | Block scope |
let |
ค่าที่ต้องเปลี่ยนระหว่างทำงาน | ได้ | Block scope |
var |
โค้ดเก่า | ได้ | Function scope |
// ใช้ const เมื่อค่าหลักไม่ต้อง assign ใหม่
const courseName = 'Web Application Development';
// ใช้ let เมื่อต้องเปลี่ยนค่า
let learnerCount = 25;
learnerCount = learnerCount + 1;
console.log(`${courseName}: ${learnerCount} learners`);
Function คือชุดคำสั่งที่นำกลับมาใช้ซ้ำได้ ช่วยให้โค้ดอ่านง่ายและแยกหน้าที่ชัดเจน ส่วน Arrow Function เป็นรูปแบบการเขียน function ที่สั้นลง เหมาะกับ callback, array method และ event handler
// Function ปกติ เหมาะกับงานที่ต้องการชื่อชัดเจน
function calculateTotal(price, quantity) {
return price * quantity;
}
// Arrow Function เหมาะกับ callback หรือ logic สั้น ๆ
const formatCurrency = (amount) => `${amount.toLocaleString()} บาท`;
const total = calculateTotal(120, 3);
console.log(formatCurrency(total));
| รูปแบบ | จุดเด่น | เหมาะกับ |
|---|---|---|
| Function Declaration | อ่านง่าย เรียกใช้ก่อนประกาศได้ | ฟังก์ชันหลักของโปรแกรม |
| Function Expression | เก็บในตัวแปรได้ | ส่งต่อเป็นค่า |
| Arrow Function | สั้น กระชับ | callback และ array method |
ในงาน front-end มักได้รับข้อมูลเป็น array เช่น รายการสินค้า รายชื่อนักศึกษา หรือโพสต์จาก API เครื่องมือสำคัญคือ map, filter, find และ reduce
const products = [
{ id: 1, name: 'Keyboard', price: 850, category: 'device' },
{ id: 2, name: 'Mouse', price: 420, category: 'device' },
{ id: 3, name: 'JavaScript Book', price: 390, category: 'book' }
];
// filter ใช้คัดเฉพาะข้อมูลที่ตรงเงื่อนไข
const devices = products.filter((product) => product.category === 'device');
// map ใช้แปลงข้อมูลเป็นรูปแบบใหม่
const productNames = devices.map((product) => product.name);
console.log(productNames);
| Method | หน้าที่ | ตัวอย่างการใช้ |
|---|---|---|
map |
แปลงข้อมูลทุกตัว | สร้าง HTML card จากรายการสินค้า |
filter |
คัดข้อมูลตามเงื่อนไข | กรองสินค้าเฉพาะหมวด |
find |
หา item แรกที่ตรงเงื่อนไข | ค้นหาสินค้าจาก id |
reduce |
รวมค่าทั้งหมด | รวมราคาสินค้าในตะกร้า |
DOM หรือ Document Object Model คือโครงสร้างของหน้า HTML ที่ browser แปลงเป็น object ทำให้ JavaScript สามารถเลือก element แก้ไขข้อความ เพิ่ม class หรือสร้าง element ใหม่ได้
%%{init: {'theme': 'base', 'themeVariables': {
'background': '#282828',
'primaryColor': '#3c3836',
'primaryTextColor': '#fbf1c7',
'primaryBorderColor': '#fabd2f',
'lineColor': '#b8bb26',
'secondaryColor': '#504945',
'tertiaryColor': '#665c54',
'fontFamily': 'Arial'
}}}%%
flowchart TD
A[document
เอกสาร] --> B[html
รากของหน้า]
B --> C[head
ข้อมูลหน้า]
B --> D[body
เนื้อหาที่แสดง]
D --> E[main
เนื้อหาหลัก]
E --> F[button
ปุ่ม]
E --> G[section
พื้นที่แสดงผล]
<h2 id="title">รายการสินค้า</h2>
<button id="loadButton">โหลดข้อมูล</button>
<p id="status">ยังไม่ได้โหลดข้อมูล</p>
<script>
// เลือก element จาก id
const loadButton = document.querySelector('#loadButton');
const statusText = document.querySelector('#status');
// เปลี่ยนข้อความเมื่อผู้ใช้คลิกปุ่ม
loadButton.addEventListener('click', () => {
statusText.textContent = 'กำลังโหลดข้อมูล...';
});
</script>
Event คือเหตุการณ์ที่เกิดขึ้นบนหน้าเว็บ เช่น click, input, submit, change หรือ keydown การใช้ event listener ทำให้หน้าเว็บตอบสนองต่อผู้ใช้ได้ทันที
<form id="searchForm">
<label for="keyword">ค้นหา</label>
<input id="keyword" name="keyword" type="search" required>
<button type="submit">ค้นหา</button>
</form>
<p id="result"></p>
<script>
const form = document.querySelector('#searchForm');
const keywordInput = document.querySelector('#keyword');
const result = document.querySelector('#result');
form.addEventListener('submit', (event) => {
// ป้องกัน browser reload หน้าเมื่อ submit form
event.preventDefault();
result.textContent = `คำค้นหา: ${keywordInput.value}`;
});
</script>
| Event | เกิดเมื่อ | ใช้กับ |
|---|---|---|
click |
ผู้ใช้คลิก | ปุ่ม เมนู card |
input |
ค่าช่องกรอกเปลี่ยน | search, form validation |
submit |
ส่งฟอร์ม | login, register, search |
change |
เลือกค่าใหม่ | select, checkbox, radio |
keydown |
กดแป้นพิมพ์ | shortcut, search suggestion |
Module ช่วยแยกโค้ดเป็นไฟล์ย่อยตามหน้าที่ เช่น ไฟล์จัดการ API ไฟล์จัดการ DOM และไฟล์หลักของหน้าเว็บ ทำให้โค้ดอ่านง่าย ทดสอบง่าย และนำกลับมาใช้ซ้ำได้
// api.js
export async function getProducts() {
const response = await fetch('/api/products.json');
return response.json();
}
// app.js
import { getProducts } from './api.js';
const products = await getProducts();
console.log(products);
<!-- ต้องระบุ type="module" เพื่อให้ browser ใช้ import/export ได้ -->
<script type="module" src="app.js"></script>
การติดต่อ API เป็นงานสำคัญของ modern front-end เพราะข้อมูลจำนวนมากมาจาก server เช่น รายการสินค้า โปรไฟล์ผู้ใช้ หรือผลการค้นหา Fetch API ใช้ส่ง request ส่วน Async/Await ทำให้โค้ด asynchronous อ่านเป็นลำดับได้ง่ายขึ้น
%%{init: {'theme': 'base', 'themeVariables': {
'background': '#282828',
'primaryColor': '#3c3836',
'primaryTextColor': '#fbf1c7',
'primaryBorderColor': '#fabd2f',
'lineColor': '#d3869b',
'secondaryColor': '#504945',
'tertiaryColor': '#665c54',
'fontFamily': 'Arial'
}}}%%
sequenceDiagram
participant U as User
ผู้ใช้
participant B as Browser
เบราว์เซอร์
participant A as API
บริการข้อมูล
U->>B: Click Load Data
B->>A: fetch('/api/products')
A-->>B: JSON Response
B-->>U: Render Cards
async function loadProducts() {
try {
const response = await fetch('/api/products.json');
if (!response.ok) {
throw new Error('ไม่สามารถโหลดข้อมูลได้');
}
const products = await response.json();
return products;
} catch (error) {
console.error(error.message);
return [];
}
}
ตัวอย่างนี้รวม DOM, Event, Array Method และ Async/Await เพื่อสร้างรายการข้อมูลที่ค้นหาได้ โดยใช้ข้อมูลจำลองแทน API จริง
<main>
<h1>Product Explorer</h1>
<form id="searchForm">
<label for="keyword">ค้นหาสินค้า</label>
<input id="keyword" type="search" placeholder="เช่น keyboard">
<button type="submit">ค้นหา</button>
</form>
<p id="status">พร้อมค้นหา</p>
<section id="productList" aria-label="รายการสินค้า"></section>
</main>
<script>
const products = [
{ name: 'Keyboard', price: 850, category: 'Device' },
{ name: 'Mouse', price: 420, category: 'Device' },
{ name: 'JavaScript Book', price: 390, category: 'Book' }
];
const form = document.querySelector('#searchForm');
const keywordInput = document.querySelector('#keyword');
const statusText = document.querySelector('#status');
const productList = document.querySelector('#productList');
function renderProducts(items) {
productList.innerHTML = items
.map((item) => `
<article>
<h2>${item.name}</h2>
<p>${item.category}</p>
<strong>${item.price} บาท</strong>
</article>
`)
.join('');
statusText.textContent = `พบข้อมูล ${items.length} รายการ`;
}
form.addEventListener('submit', (event) => {
event.preventDefault();
const keyword = keywordInput.value.toLowerCase();
const filteredProducts = products.filter((product) =>
product.name.toLowerCase().includes(keyword)
);
renderProducts(filteredProducts);
});
renderProducts(products);
</script>
| รายการตรวจ | คำถามที่ต้องตอบ |
|---|---|
| Variable | ใช้ const และ let เหมาะสมหรือไม่ |
| Function | แยก logic เป็น function ที่อ่านง่ายหรือไม่ |
| DOM | เลือก element ด้วย selector ที่ชัดเจนหรือไม่ |
| Event | ใช้ addEventListener และ preventDefault ถูกที่หรือไม่ |
| Fetch | จัดการ loading/error เมื่อเรียก API หรือไม่ |
| Rendering | อัปเดต DOM เฉพาะส่วนที่จำเป็นหรือไม่ |
| Maintainability | โค้ดแบ่งหน้าที่และตั้งชื่ออ่านเข้าใจหรือไม่ |
สร้างหน้าเว็บ Product Explorer หรือ Student Directory ที่มีความสามารถต่อไปนี้:
filterlet, const และ var ต่างกันอย่างไรaddEventListener สำคัญต่อหน้าเว็บแบบ interactive อย่างไรmap และ filter ต่างกันอย่างไรasync/await ช่วยให้โค้ดติดต่อ API อ่านง่ายขึ้นอย่างไร