HTML 文件的骨幹是標籤。
根據文件物件模型 (DOM),每個 HTML 標籤都是一個物件。巢狀標籤是封閉標籤的「子代」。標籤內的文字也是一個物件。
所有這些物件都可以使用 JavaScript 存取,我們可以使用它們來修改頁面。
例如,document.body
是表示 <body>
標籤的物件。
執行這段程式碼會讓 <body>
變成紅色 3 秒鐘
document.body.style.background = 'red'; // make the background red
setTimeout(() => document.body.style.background = '', 3000); // return back
這裡我們使用 style.background
來變更 document.body
的背景顏色,但還有許多其他屬性,例如
innerHTML
– 節點的 HTML 內容。offsetWidth
– 節點寬度(以像素為單位)- …等等。
我們很快就會學到更多操作 DOM 的方法,但首先我們需要了解它的結構。
DOM 的範例
讓我們從以下簡單的文件開始
<!DOCTYPE HTML>
<html>
<head>
<title>About elk</title>
</head>
<body>
The truth about elk.
</body>
</html>
DOM 將 HTML 表示為標籤的樹狀結構。它看起來像這樣
在上面的圖片中,您可以按一下元素節點,它們的子節點將會展開/收合。
每個樹狀節點都是一個物件。
標籤是元素節點(或僅為元素),並形成樹狀結構:<html>
在根部,然後 <head>
和 <body>
是它的子節點,依此類推。
元素內的文字形成文字節點,標示為 #text
。文字節點僅包含一個字串。它可能沒有子節點,而且總是樹狀結構的葉子節點。
例如,<title>
標籤的文字為 "關於麋鹿"
。
請注意文字節點中的特殊字元
- 換行:
↵
(在 JavaScript 中稱為\n
) - 空白:
␣
空白和換行是完全有效的字元,就像字母和數字一樣。它們形成文字節點,並成為 DOM 的一部分。因此,例如,在上面的範例中,<head>
標籤在 <title>
之前包含一些空白,而該文字會成為 #text
節點(它僅包含換行和一些空白)。
只有兩個頂層例外
- 由於歷史原因,
<head>
之前的空白和換行會被忽略。 - 如果我們在
</body>
之後放置一些內容,則會自動將其移到body
內部,在最後面,因為 HTML 規範要求所有內容都必須在<body>
內部。因此,</body>
之後不能有任何空白。
在其他情況下,一切都很簡單 – 如果文件中有空白(就像任何字元一樣),則它們會在 DOM 中成為文字節點,如果我們將它們移除,則不會有任何空白。
這裡沒有僅空白的文字節點
<!DOCTYPE HTML>
<html><head><title>About elk</title></head><body>The truth about elk.</body></html>
通常會使用 DOM 的瀏覽器工具(稍後會介紹)不會顯示文字開頭/結尾的空白和標籤之間的空文字節點(換行)。
開發人員工具會以這種方式節省螢幕空間。
在進一步的 DOM 圖片中,當它們不相關時,我們有時會省略它們。此類空白通常不會影響文件的顯示方式。
自動更正
如果瀏覽器遇到格式錯誤的 HTML,它會在建立 DOM 時自動更正。
例如,最上層標籤永遠是 <html>
。即使它不存在於文件,它也會存在於 DOM 中,因為瀏覽器會建立它。<body>
也是一樣。
例如,如果 HTML 檔只有一個單字 "Hello"
,瀏覽器會將它包在 <html>
和 <body>
中,並加入必要的 <head>
,而 DOM 會是
在產生 DOM 時,瀏覽器會自動處理文件中的錯誤、關閉標籤等等。
一個未關閉標籤的文件
<p>Hello
<li>Mom
<li>and
<li>Dad
…會變成一個正常的 DOM,因為瀏覽器會讀取標籤並還原遺失的部分
<tbody>
一個有趣的「特殊狀況」是表格。根據 DOM 規範,它們必須有 <tbody>
標籤,但 HTML 文字可以省略它。然後瀏覽器會自動在 DOM 中建立 <tbody>
。
對於 HTML
<table id="table"><tr><td>1</td></tr></table>
DOM 結構會是
看到了嗎?<tbody>
憑空出現了。在處理表格時,我們應該記住這一點,以避免驚喜。
其他節點類型
除了元素和文字節點,還有一些其他節點類型。
例如,註解
<!DOCTYPE HTML>
<html>
<body>
The truth about elk.
<ol>
<li>An elk is a smart</li>
<!-- comment -->
<li>...and cunning animal!</li>
</ol>
</body>
</html>
我們可以在這裡看到一個新的樹節點類型 – 註解節點,標記為 #comment
,在兩個文字節點之間。
我們可能會想 – 為什麼註解會被加入到 DOM 中?它不會以任何方式影響視覺呈現。但有一個規則 – 如果某個東西在 HTML 中,那麼它也必須在 DOM 樹中。
HTML 中的一切,甚至是註解,都會成為 DOM 的一部分。
甚至 HTML 最開頭的 <!DOCTYPE...>
指令也是一個 DOM 節點。它在 DOM 樹中就在 <html>
之前。很少人知道這一點。我們不會碰那個節點,我們甚至不會在圖表中畫出來,但它就在那裡。
表示整個文件的 document
物件,正式來說,也是一個 DOM 節點。
有 12 種節點類型。在實務上,我們通常只會使用其中的 4 種
document
– DOM 的「進入點」。- 元素節點 – HTML 標籤,樹的建構區塊。
- 文字節點 – 包含文字。
- 註解 – 有時我們可以將資訊放在那裡,它不會顯示,但 JS 可以從 DOM 中讀取它。
親自看看
若要即時查看 DOM 結構,請嘗試使用 Live DOM Viewer。只要在文件中輸入,它就會立即顯示為 DOM。
探索 DOM 的另一種方法是使用瀏覽器開發人員工具。事實上,這是我們在開發時使用的工具。
為此,請開啟網頁 elk.html,開啟瀏覽器開發人員工具,然後切換到元素標籤。
它應該如下所示
您可以看到 DOM,按一下元素,查看其詳細資料等。
請注意,開發人員工具中的 DOM 結構已簡化。文字節點僅顯示為文字。而且完全沒有「空白」(僅空白)文字節點。這很好,因為我們大部分時間都對元素節點感興趣。
按一下左上角的 按鈕,讓我們可以使用滑鼠(或其他指標裝置)從網頁中選擇一個節點並「檢查」它(在元素標籤中捲動到它)。當我們有一個巨大的 HTML 頁面(以及對應的巨大 DOM)並且想要在其中查看特定元素的位置時,這非常有用。
另一種方法是只需在網頁上按一下滑鼠右鍵,然後在內容選單中選擇「檢查」。
在工具的右側有以下子標籤
- 樣式 – 我們可以看到應用於目前元素規則的 CSS,包括內建規則(灰色)。幾乎所有內容都可以直接編輯,包括下方方塊的維度/邊界/填塞。
- 已計算 – 查看應用於元素的 CSS 屬性:對於每個屬性,我們可以看到給予它的規則(包括 CSS 繼承等)。
- 事件聆聽器 – 查看附加到 DOM 元素的事件聆聽器(我們將在教學課程的下一部分中介紹它們)。
- …等等。
研究它們的最佳方法是到處按一下。大多數值都可以直接編輯。
與主控台互動
當我們使用 DOM 時,我們也可能想要對其套用 JavaScript。例如:取得一個節點並執行一些程式碼來修改它,以查看結果。以下是一些在元素標籤和主控台之間移動的提示。
開始
- 在元素標籤中選擇第一個
<li>
。 - 按 Esc – 它會在「元素」標籤正下方開啟主控台。
現在最後選取的元素會以 $0
顯示,前一個選取的元素會以 $1
顯示,以此類推。
我們可以在這些元素上執行指令。例如,$0.style.background = 'red'
會讓選取的清單項目變成紅色,如下所示
這就是從「元素」中在主控台中取得節點的方法。
還有一個反向途徑。如果有一個變數參照 DOM 節點,我們可以在主控台中使用指令 inspect(node)
在「元素」面板中查看該節點。
或者我們也可以在主控台中輸出 DOM 節點,並在「原地」探索,如下方的 document.body
當然,這是為了除錯目的。從下一章開始,我們將使用 JavaScript 存取和修改 DOM。
瀏覽器開發人員工具在開發過程中非常有幫助:我們可以探索 DOM、嘗試各種操作,並查看哪裡出錯。
摘要
HTML/XML 文件在瀏覽器中以 DOM 樹的形式呈現。
- 標籤會變成元素節點,並形成結構。
- 文字會變成文字節點。
- …等等,HTML 中的每個元素在 DOM 中都有其位置,甚至包括註解。
我們可以使用開發人員工具來檢查 DOM,並手動修改它。
在這裡,我們介紹了基礎知識,也就是最常使用且最重要的操作,以作為入門。在 https://developers.google.com/web/tools/chrome-devtools 上有關於 Chrome 開發人員工具的詳細文件。學習這些工具的最佳方法是到處按按看,閱讀選單:大部分選項都很明顯。之後,當你大致了解這些選項後,再閱讀文件並學習其餘部分。
DOM 節點有許多屬性和方法,讓我們可以在節點之間移動、修改節點、在頁面上移動,以及執行更多操作。我們將在下一章中深入探討這些屬性和方法。
留言
<code>
標籤,若要插入多行程式碼,請將其包覆在<pre>
標籤中,若要插入超過 10 行程式碼,請使用 sandbox(plnkr、jsbin、codepen…)