上一篇我們學會了變數、函式與流程控制,但程式只在 Console 裡執行,網頁本身並不會有任何變化。這一篇要學的是 JavaScript 與網頁互動的關鍵:DOM 操作與事件處理。學會之後,你就能做出按鈕點擊、表單驗證、動態新增內容等功能。
一、什麼是 DOM?
DOM(Document Object Model,文件物件模型)是瀏覽器把 HTML 轉換成的「樹狀結構」。每一個標籤都是樹上的一個節點,JavaScript 可以透過 DOM 讀取或修改網頁的內容、樣式與結構。
document
└─ html
├─ head
│ └─ title
└─ body
├─ h1
└─ p
在 JavaScript 中,document 物件就是進入這棵樹的入口。
二、選取元素
要操作元素,必須先「找到」它。現代寫法建議使用 querySelector 與 querySelectorAll,語法與 CSS 選擇器相同:
// 選取第一個符合的元素
const title = document.querySelector("h1");
const box = document.querySelector("#box"); // 以 id 選取
const item = document.querySelector(".item"); // 以 class 選取
// 選取所有符合的元素(回傳 NodeList,可用 for...of 或 forEach 走訪)
const items = document.querySelectorAll(".item");
items.forEach(el => console.log(el.textContent));
| 方法 | 回傳結果 |
|---|---|
| querySelector(選擇器) | 第一個符合的元素,找不到為 null |
| querySelectorAll(選擇器) | 所有符合的元素(NodeList) |
| getElementById(id) | 指定 id 的元素 |
三、修改內容、屬性與樣式
const title = document.querySelector("h1");
// 1. 修改文字內容
title.textContent = "新的標題";
// 2. 修改 HTML 內容(注意:不要放入使用者輸入的內容,有安全風險)
title.innerHTML = "新的 <em>標題</em>";
// 3. 修改屬性
const img = document.querySelector("img");
img.setAttribute("src", "photo.jpg");
img.alt = "風景照片";
// 4. 修改樣式
title.style.color = "tomato";
title.style.fontSize = "32px";
// 5. 切換 class(最推薦的樣式控制方式)
title.classList.add("active");
title.classList.remove("active");
title.classList.toggle("active"); // 有就移除,沒有就加入
小提醒:需要大量變更樣式時,建議在 CSS 寫好 class,再用 classList 切換,程式碼會比直接改 style 更好維護。
四、建立與刪除元素
const list = document.querySelector("#list");
// 建立新元素
const li = document.createElement("li");
li.textContent = "新的項目";
// 加到清單最後面
list.appendChild(li);
// 加到最前面
list.prepend(li);
// 刪除元素
li.remove();
五、事件處理
「事件」是使用者或瀏覽器所發生的動作,例如點擊、輸入、滑鼠移動、頁面載入完成等。我們使用 addEventListener 來「監聽」事件:
const btn = document.querySelector("#btn");
btn.addEventListener("click", function (event) {
console.log("按鈕被點擊了!");
console.log(event.target); // 觸發事件的元素
});
常見的事件類型:
| 事件 | 觸發時機 |
|---|---|
| click | 滑鼠點擊 |
| input | 輸入框內容改變(每打一個字就觸發) |
| submit | 表單送出 |
| keydown | 按下鍵盤按鍵 |
| mouseover | 滑鼠移入元素 |
| DOMContentLoaded | HTML 解析完成 |
阻止預設行為
表單送出時,瀏覽器預設會重新整理頁面。若想自行處理,要使用 preventDefault():
const form = document.querySelector("#myForm");
form.addEventListener("submit", function (e) {
e.preventDefault(); // 阻止頁面重新整理
console.log("表單已攔截,由 JavaScript 處理");
});
事件委派(Event Delegation)
如果清單中有很多項目,逐一綁定事件既麻煩,新增的項目也不會有事件。更好的做法是把事件綁在「父元素」上,利用事件會往上冒泡的特性來判斷是哪個子元素被點擊:
const list = document.querySelector("#list");
list.addEventListener("click", function (e) {
if (e.target.tagName === "LI") {
e.target.classList.toggle("done");
}
});
六、綜合範例:待辦事項清單
把前面學到的整合起來,完成一個簡單的待辦清單。將下列程式碼存成 todo.html,用瀏覽器開啟即可測試:
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>待辦清單</title>
<style>
.done { text-decoration: line-through; color: gray; }
li { cursor: pointer; margin: 6px 0; }
</style>
</head>
<body>
<h1>我的待辦清單</h1>
<form id="todoForm">
<input type="text" id="todoInput" placeholder="輸入待辦事項" required>
<button type="submit">新增</button>
</form>
<ul id="todoList"></ul>
<script>
const form = document.querySelector("#todoForm");
const input = document.querySelector("#todoInput");
const list = document.querySelector("#todoList");
// 新增項目
form.addEventListener("submit", function (e) {
e.preventDefault();
const text = input.value.trim();
if (text === "") return;
const li = document.createElement("li");
li.textContent = text;
list.appendChild(li);
input.value = "";
input.focus();
});
// 事件委派:點一下標示完成,連點兩下刪除
list.addEventListener("click", function (e) {
if (e.target.tagName === "LI") {
e.target.classList.toggle("done");
}
});
list.addEventListener("dblclick", function (e) {
if (e.target.tagName === "LI") {
e.target.remove();
}
});
</script>
</body>
</html>
七、常見錯誤與提醒
- 找不到元素(null):如果
<script>寫在<head>,執行時 HTML 還沒載入。解法是把 script 放在</body>前,或加上defer屬性。 - innerHTML 的安全問題:直接把使用者輸入的內容放進
innerHTML可能造成 XSS 攻擊,一般文字請使用textContent。 - querySelectorAll 的結果:它回傳的是 NodeList,不是真正的陣列,需要用
Array.from()轉換後才能使用map、filter。
八、練習題
- 製作一個按鈕,每點一次,畫面上的數字就加 1。
- 製作一個「切換深色/淺色模式」的按鈕,使用
classList.toggle完成。 - 在待辦清單範例中,加入「清除全部」按鈕。
- 製作一個輸入框,並在下方即時顯示已輸入的字數(提示:使用
input事件)。
結語
這篇介紹了如何選取元素、修改內容與樣式、動態建立元素,以及用事件讓網頁與使用者互動。DOM 與事件是前端開發的核心,建議多動手練習。下一篇將介紹 非同步程式設計(Promise、async/await 與 fetch),讓你的網頁能向伺服器取得資料。如果有任何問題,歡迎在下方留言討論!
沒有留言:
張貼留言