HTML DOM 破解:新手完全指南,帶你深入理解網頁結構
更新日期: 2024 年 9 月 14 日
本文是一篇專門為新手撰寫的 HTML DOM (Document Object Model) 入門指南。
在你開始創建網頁,或者試著用 JavaScript 增強網頁互動性之前,理解 DOM 的概念是非常重要的。
本文的目標,是幫助你建立一個堅實的 DOM 基礎知識,讓你能夠輕鬆理解和操作網頁的結構。
什麼是 DOM?
在深入研究 DOM 之前,我們需要了解一下 HTML 和 DOM 的基本知識。
HTML,全稱 HyperText Markup Language,是一種用於建立網頁的標記語言。
一個 HTML 文件就是由許多的 HTML 元素組成的,這些元素由標籤 (<>) 來定義,像是 <body>、<div>、 <p> 等等,這些標籤將頁面分割成一個個區塊。
DOM 則是 Document Object Model 的縮寫,它讓我們可以透過程式碼,來操作網頁的內容、結構、和風格。
我們可以將這個結構想像成一張「物件的地圖」。該地圖描述了 HTML 頁面中,每個區塊彼此之間的關係。
DOM 樹
事實上,DOM 將 HTML 網頁轉換成一種物件導向的樹狀結構(由上往下生長),並使我們可利用程式語言進行操作。
在 DOM 樹中,每個 HTML 標籤都會被轉換成一個「節點」(Node),這些節點可以有父節點、子節點、以及兄弟節點的關係。
在 DOM 樹的頂端,有一個特殊的節點稱為「根節點」(Root node)。
在 HTML 文檔中,這個節點就是 Document 物件,代表整個網頁。
接著,這個 Document 物件會有一個或多個子節點,對應到 HTML 標籤。
例如,<html>、<head>、以及 <body> 等標籤就是 Document 的子節點。
此外,這些子節點又可以再有自己的子節點,以此類推,形成一個樹狀結構。
使用 JavaScript 來操作 DOM
JavaScript 是網頁開發者最常使用來與 DOM 互動的程式語言。
透過 JavaScript,我們可以讀取、改變、新增或刪除 DOM 節點,從而改變網頁的內容和結構。
選擇節點
要操作 DOM,首先需要選取節點。
Document 物件提供了許多 JavaScript 方法可以選取節點,以下是一些常見的方法:
getElementsByClassName(name)
透過元素的 class name 選取元素,返回一個包含所有符合的元素的 NodeList
getElementsByTagName(name)
透過元素的 tag name 選取元素,返回一個包含所有符合的元素的 NodeList
querySelectorAll(selector)
透過 CSS 選擇器選取元素,返回一個包含所有符合的元素的 NodeList
getElementById(id)
透過 HTML 元素的 ID 選取元素。
querySelector(selector)
透過 CSS 選擇器選取元素,只返回第一個符合的元素。
補充一:NodeList 是什麼意思?
在 DOM (Document Object Model) 程式設計中,NodeList 是一種數據結構,可以看做是節點的集合或列表。
這裡的節點(Node)是 DOM 中的基本組成單位,比如一個 HTML 文件的元素、屬性和文本都是節點。
當你透過某些 DOM 方法,如 getElementsByTagName 或 querySelectorAll 等,選取某些元素時,這些方法會返回一個 NodeList。這個 NodeList 包含了所有符合你選取條件的節點。
在中文環境下,NodeList 通常被翻譯為「節點列表」或者「節點集合」。
補充二:NodeList 資料類型介紹
NodeList 是 DOM (Document Object Model) 中的一種資料類型,它是一種類似陣列 (array) 的集合,包含了一組節點 (node)。
但需要注意的是,雖然 NodeList 在某些行為上與陣列類似(例如可以使用索引來訪問元素,可以用.length 屬性來獲取其長度)。
它並不是真正的 JavaScript 陣列,因此不包含所有陣列的方法,比如 .push()、.pop() 等。
來看一個實際的例子,假設我們有以下的 HTML 結構:
<ul id="my-list">
<li>項目一</li>
<li>項目二</li>
<li>項目三</li>
</ul>
在 JavaScript 中,我們可以用 document.querySelectorAll 方法來獲取所有的 <li>
元素,並將它們儲存在一個 NodeList 中:
let listItems = document.querySelectorAll("#my-list li");
這時,listItems
就是一個 NodeList,它包含了三個 <li>
節點。我們可以用索引來訪問這些節點:
console.log(listItems[0]); // 輸出: <li>項目一</li>
console.log(listItems[1]); // 輸出: <li>項目二</li>
console.log(listItems[2]); // 輸出: <li>項目三</li>
我們也可以用 .length 屬性來獲取 NodeList 的長度:
console.log(listItems.length); // 輸出: 3
但是,由於 NodeList 不是真正的陣列,所以我們不能使用陣列的方法,例如:
listItems.push('<li>新的項目</li>'); // 錯誤:listItems.push is not a function
改變節點
選取節點後,我們可以改變它的屬性、CSS 樣式,或者直接改變它的內容:
.innerHTML
可以讀取或改變元素的 HTML 內容
.style
可以讀取或改變元素的 CSS 樣式
.getAttribute(name)
可以讀取元素的屬性
.setAttribute(name,value)
可以設定元素的屬性
新增和刪除節點
除了讀取和改變節點,JavaScript 也可以新增或刪除節點:
removeChild(node)
移除一個子節點。
createTextNode(data)
創建一個新的文本節點。
appendChild(node)
在當前節點的最後一個子節點後新增一個子節點。
createElement(tagName)
創建一個新的元素節點。
insertBefore(newNode,referenceNode)
在參考節點之前新增一個新節點。
補充:「文本節點」與「元素節點」差在哪?
在 DOM (Document Object Model) 中,「節點」 (Node) 是一種基本的資料結構。
DOM 中的所有內容都可以看作是節點,包括元素、文本、註解等等。「元素節點」和「文本節點」都是 DOM 節點的類型,但它們表示的內容與功能有所不同。
簡單來說,元素節點代表著 HTML 文件的結構(也就是元素如何嵌套和組織),而文本節點則代表元素內部的具體內容。
透過以上的方法,我們可以用 JavaScript 來動態地操作 DOM,達到變更網頁的目的。
這是 JavaScript 在網頁開發中的重要角色,也是建立動態網頁和實現互動功能的基礎。
HTML 結合 DOM 範例說明
以下,我們將透過一個基本的範例,來解釋如何使用 JavaScript 操作 DOM。
讓我們首先從一個簡單的 HTML 文件開始:
<!DOCTYPE html>
<html>
<head>
<title>JavaScript DOM 操作範例</title>
</head>
<body>
<h1 id="title">歡迎來到我的網站</h1>
<p class="content">這是一個範例段落。</p>
<p class="content">這是另一個範例段落。</p>
</body>
</html>
在這個 HTML 文件中,我們有一個標題 (<h1>) 和兩個段落 (<p>)。標題元素具有 id 「title」,兩個段落元素都有 class 「content」。
現在,我們要使用 JavaScript 來操作這個 DOM。
選取元素
首先,我們可以使用 getElementById 來選取具有特定 id 的元素:
let titleElement = document.getElementById("title");
我們也可以使用 getElementsByClassName 來選取所有具有特定 class 的元素:
let contentElements = document.getElementsByClassName("content");
注意:getElementsByClassName
返回的是一個 NodeList(節點列表)。
修改元素內容
我們可以使用 innerHTML
屬性來修改元素的內容:
titleElement.innerHTML = "歡迎來到我的新網站";
修改元素屬性
我們可以使用 setAttribute
函數來修改元素的屬性:
titleElement.setAttribute("style", "color: red");
修改元素風格
我們也可以直接修改元素的 CSS 屬性來改變它的風格:
titleElement.style.fontSize = "2em";
經過上述的 JavaScript 操作,我們改變了標題元素的內容、顏色和字體大小。
同樣地,我們也可以對其他元素進行各種操作。
補充:DOM 相關代碼要放在哪裡?
通常,為了確保整個頁面已經加載完畢,我們會將 <script> 標籤放在 HTML 文件的最後,就在閉合的 </body> 標籤之前。
以下是一個範例:
<!DOCTYPE html>
<html>
<head>
<title>JavaScript DOM 操作範例</title>
</head>
<body>
<h1 id="title">歡迎來到我的網站</h1>
<p class="content">這是一個範例段落。</p>
<p class="content">這是另一個範例段落。</p>
<script>
var titleElement = document.getElementById("title");
// 其他的 JavaScript 代碼...
</script>
</body>
</html>
然而,在實際開發中,為了維護方便,我們通常會將 JavaScript 代碼寫在一個獨立的 .js 文件中,然後在HTML文件中引用這個.js文件。
這樣可以讓 HTML 文件保持整潔,並將結構(HTML)、樣式(CSS)和行為(JavaScript)分開。
這是一種被廣泛接受的最佳安排方式。例如:
<!DOCTYPE html>
<html>
<head>
<title>JavaScript DOM 操作範例</title>
</head>
<body>
<h1 id="title">歡迎來到我的網站</h1>
<p class="content">這是一個範例段落。</p>
<p class="content">這是另一個範例段落。</p>
<script src="script.js"></script>
</body>
</html>
什麼是 DOM 事件
DOM 「事件」是在網頁或瀏覽器環境中,發生的特定動作或行為。
例如點擊按鈕、滾動滾輪、按下鍵盤鍵等。
它讓 JavaScript 在這些事件動作發生時,可以執行特定的代碼,並促成互動式網頁的基本機制。
常見的 DOM 事件
DOM 定義了許多種事件,以下列出一些常見的事件:
- click:當使用者點擊元素時觸發。
- mousemove:當滑鼠在元素上移動時觸發。
- keydown:當使用者按下鍵盤按鍵時觸發。
- load:當瀏覽器完成載入網頁時觸發。
- change:當表單元素的值被改變時觸發。
事件監聽器
若想在 JavaScript 中處理事件,我們需要添加「事件監聽器」到指定的元素上。
監聽器是一個函數,當事件被觸發時,這個函數就會被自動啟用(呼叫)。
我們可以使用 addEventListener 方法,添加監聽器:
element.addEventListener(event, function);
例如,以下的代碼會在按鈕被點擊時,顯示一個提示框:
let button = document.getElementById('myButton');
button.addEventListener('click', function() {
alert('Button was clicked!');
});
事件物件
當某些事件(如點擊、滑鼠移動、按鍵等)在網頁上觸發時,瀏覽器會自動創建一個事件物件,並將其傳遞給處理該事件的函數。
事件物件包含了關於該事件的詳細資訊。
例如:事件的類型、觸發事件的元素、事件發生的時間、滑鼠的位置等。
下面是一個簡單的範例,示範了如何在 JavaScript 中使用事件物件:
// 假設我們有一個按鈕
var btn = document.getElementById('myButton');
// 我們可以給這個按鈕添加一個點擊事件的監聽器
btn.addEventListener('click', function(event) {
// 當按鈕被點擊時,這個函數將會被調用
// event 這個參數就是事件物件,它包含了關於這次點擊事件的資訊
// 例如,我們可以獲取點擊事件的發生時間
console.log('事件發生時間:', event.timeStamp);
// 或者獲取觸發事件的元素(在這個案例中,就是按鈕本身)
console.log('觸發事件的元素:', event.target);
});
事件物件的屬性和方法,取決於事件的類型。
例如,「點擊事件」的物件和「鍵盤事件」的物件,將有不同的屬性和方法。
因為這兩種事件提供的資訊是不同的。
你可以參考 MDN 文檔或其他參考,來了解特定事件物件的所有屬性和方法。
DOM 的常見問題和解決方案
操作 DOM 在開發過程中,可以遇到多種問題。
以下將列出一些常見的問題,以及相對應的解決方案。
跨瀏覽器的兼容性
不同的瀏覽器可能對 DOM API 的實現有輕微的差異。
這可能導致在一個瀏覽器中運作正常的程式碼,在另一個瀏覽器中卻無法正常運作。
解決方案:使用已知具有良好跨瀏覽器兼容性的 JavaScript 函式庫(例如 jQuery)可以解決這個問題。
另外,一個良好的做法,是經常使用瀏覽器開發者工具,來測試和調試您的程式碼。
DOM 操作效能
頻繁的 DOM 操作(如添加或刪除元素)可能導致瀏覽器重新渲染網頁,影響性能。
解決方案:透過合理規劃 DOM 操作、使用文檔片段(Document Fragments)。
或者是儘量一次性完成較大的 DOM 變動等方式,可以提高效能。
複雜的事件處理
如果對多個元素添加事件處理器,可能會導致代碼混亂難以管理。
解決方案:透過事件代理或委派,將事件處理器添加到父元素上。
同時利用事件冒泡機制,根據事件的目標元素執行不同的動作。
DOM 查找的效能
反覆使用 document.getElementById 或 document.querySelector 來查找元素,會降低程式碼效能。
解決方案: 將查找到的元素儲存在變量中,以減少未來的查找次數。例如:
let myElement = document.getElementById('myElement');
以上就是一些操作 DOM 時可能會遇到的問題以及解決方案。
有了這些了解,我們就可以更有效地使用 DOM API,創建出更好的網頁應用。
結語
經過本文的解析與實例練習,相信你對於 HTML DOM 有了更深入的了解。
然而,與任何技術一樣,理解並精通 DOM 需要時間和練習。
我們鼓勵您不斷實驗和練習,透過實作與解決問題來熟悉 DOM 的操作。
參考資源
以下是一些您可能會對 DOM 進一步學習的有用資源:
- Mozilla Developer Network (MDN) – DOM 指南:Mozilla 提供的 DOM 教學,深入淺出,內容豐富。
- JavaScript.info – Document:這是一個深入介紹如何使用 JavaScript 來操作 DOM 的教程。
- W3Schools – HTML DOM:W3Schools 網站提供了大量關於 DOM 的教學,包含許多範例讓你進行實作練習。
- Google Developers – DOM Enlightenment:Google 的開發者工具中關於 DOM 的一部分,內含各種使用情境和範例。
- Eloquent JavaScript – The Document Object Model:這是一本 JavaScript 的線上書籍,第十四章完整地介紹了 DOM。
學習的過程中,如果遇到疑難雜症,別忘了您還可以在如 Stack Overflow 等討論區尋求解答。
一起加油,並且享受學習的過程!