JavaScript
DOM Manipulation
Select elements (querySelector)
เรียนรู้การเข้าถึง HTML elements ด้วย querySelector และ querySelectorAll พร้อม CSS selector syntax และการป้องกัน null
DOM คืออะไร และทำไมต้องเลือก element
DOM (Document Object Model) คือโครงสร้างแบบ tree ที่ browser สร้างขึ้นจาก HTML ของหน้าเว็บ แต่ละ tag เช่น `<h1>`, `<p>`, `<div>` กลายเป็น node ใน tree นั้น JavaScript เข้าถึง tree ทั้งหมดผ่านออบเจกต์ชื่อ `document`
HTML นี้ browser จะแปลงเป็น DOM tree — แต่ละ tag คือ node หนึ่งตัว
<body>
<h1 id="title">สวัสดี DOM</h1>
<p class="intro">นี่คือ paragraph แรก</p>
<ul>
<li>รายการ 1</li>
<li>รายการ 2</li>
</ul>
</body>ก่อนที่ JavaScript จะอ่านค่า เปลี่ยนข้อความ หรือจัดการอะไรกับ element ใด ๆ ได้ จะต้อง "เลือก" element นั้นออกมาก่อนเสมอ `querySelector` และ `querySelectorAll` คือสองเครื่องมือหลักที่ใช้เลือก element จาก DOM
`document.querySelector()` — เลือก element เดียว
`document.querySelector(selector)` รับ CSS selector แล้วคืน **element แรกสุด** ที่ตรงกับ selector นั้น ถ้าไม่เจอ element ใดเลย จะคืนค่า `null`
querySelector คืน element ตัวเดียวเสมอ — ถ้ามีหลายตัวที่ match จะได้แค่ตัวแรก
// เลือกด้วย id
const title = document.querySelector("#title");
// เลือกด้วย class
const intro = document.querySelector(".intro");
// เลือกด้วย tag
const firstItem = document.querySelector("li");
console.log(title); // <h1 id="title">...</h1>
console.log(intro); // <p class="intro">...</p>
console.log(firstItem); // <li>รายการ 1</li> ← คืนแค่ตัวแรกเพราะ `querySelector` อาจคืน `null` ได้ ควรตรวจสอบก่อนใช้งาน element เสมอ มิฉะนั้นจะเกิด error เมื่อพยายามเข้าถึง property ของ `null`
null-check ป้องกัน TypeError: Cannot set properties of null
const btn = document.querySelector("#submit-btn");
// ❌ อันตราย — ถ้า btn เป็น null จะ error
btn.style.color = "red";
// ✅ ปลอดภัย — ตรวจก่อนใช้
if (btn) {
btn.style.color = "red";
}`document.querySelectorAll()` — เลือกหลาย elements
`document.querySelectorAll(selector)` คืน **NodeList** ซึ่งเป็นคอลเลกชันของทุก element ที่ตรงกับ selector NodeList ไม่ใช่ Array แต่วน loop ด้วย `forEach` ได้โดยตรง
querySelectorAll คืนทุก element ที่ match — ใช้ forEach วนผ่านได้ทันที
const items = document.querySelectorAll("li");
console.log(items); // NodeList(2) [li, li]
console.log(items.length); // 2
items.forEach(function(item) {
console.log(item); // log ทุก <li> ทีละตัว
});ความต่างหลักระหว่างสองฟังก์ชัน: - `querySelector` → คืน element เดียว (หรือ `null`) - `querySelectorAll` → คืน NodeList เสมอ (ถ้าไม่เจอจะได้ NodeList ว่าง ไม่ใช่ `null`)
CSS Selectors ที่ใช้กับ querySelector ได้
ทั้ง `querySelector` และ `querySelectorAll` รับ CSS selector syntax — เหมือนกับที่เขียนใน stylesheet ทุกประการ
| Selector | ตัวอย่าง | เลือกอะไร |
|---|---|---|
| tag | querySelector("h1") | tag ชื่อ h1 |
| .class | querySelector(".card") | element ที่มี class="card" |
| #id | querySelector("#menu") | element ที่มี id="menu" |
| [attr] | querySelector("[disabled]") | element ที่มี attribute disabled |
| [attr=value] | querySelector("[type='text']") | input ที่มี type="text" |
| nested (space) | querySelector("ul li") | li ที่อยู่ใน ul |
| combined | querySelector("ul li.active") | li.active ที่อยู่ใน ul |
selector ที่ซับซ้อนขึ้นก็ใช้ได้เหมือนใน CSS เลย
// เลือก li ที่มี class "active" ภายใน ul เท่านั้น
const activeItem = document.querySelector("ul li.active");
// เลือกทุก input ประเภท text
const textInputs = document.querySelectorAll("input[type='text']");ข้อควรระวัง
- **ตรวจ null เสมอ** — `querySelector` คืน `null` เมื่อไม่พบ element ถ้าไม่ check ก่อนใช้จะเกิด TypeError
- **NodeList ≠ Array** — `querySelectorAll` คืน NodeList ที่ใช้ `forEach` ได้ แต่ใช้ `map`, `filter`, `reduce` โดยตรงไม่ได้ ต้องแปลงด้วย `Array.from()` ก่อน
- **querySelector คืนแค่ตัวแรก** — ถ้าต้องการทุก element ที่ match ให้ใช้ `querySelectorAll`
- **selector ผิด syntax** — ถ้า selector ไม่ถูกต้อง browser จะ throw SyntaxError ทันที ไม่ใช่คืน null