Javascript DOM 樹

2023-02-17 10:54 更新

HTML 文檔的主干是標(biāo)簽(tag)。

根據(jù)文檔對象模型(DOM),每個 HTML 標(biāo)簽都是一個對象。嵌套的標(biāo)簽是閉合標(biāo)簽的“子標(biāo)簽(children)”。標(biāo)簽內(nèi)的文本也是一個對象。

所有這些對象都可以通過 JavaScript 來訪問,我們可以使用它們來修改頁面。

例如,document.body 是表示 <body> 標(biāo)簽的對象。

運行這段代碼會使 <body> 保持 3 秒紅色狀態(tài):

document.body.style.background = 'red'; // 將背景設(shè)置為紅色

setTimeout(() => document.body.style.background = '', 3000); // 恢復(fù)回去

在這,我們使用了 style.background 來修改 document.body 的背景顏色,但是還有很多其他的屬性,例如:

  • ?innerHTML? —— 節(jié)點的 HTML 內(nèi)容。
  • ?offsetWidth? —— 節(jié)點寬度(以像素度量)
  • ……等。

很快,我們將學(xué)習(xí)更多操作 DOM 的方法,但首先我們需要了解 DOM 的結(jié)構(gòu)。

DOM 的例子

讓我們從下面這個簡單的文檔(document)開始:

<!DOCTYPE HTML>
<html>
<head>
  <title>About elk</title>
</head>
<body>
  The truth about elk.
</body>
</html>

DOM 將 HTML 表示為標(biāo)簽的樹形結(jié)構(gòu)。它看起來如下所示:


在上面的圖片中,你可以點擊元素(element)節(jié)點,它們的子節(jié)點會打開/折疊。

每個樹的節(jié)點都是一個對象。

標(biāo)簽被稱為 元素節(jié)點(或者僅僅是元素),并形成了樹狀結(jié)構(gòu):<html> 在根節(jié)點,<head> 和 <body> 是其子項,等。

元素內(nèi)的文本形成 文本節(jié)點,被標(biāo)記為 #text。一個文本節(jié)點只包含一個字符串。它沒有子項,并且總是樹的葉子。

例如,<title> 標(biāo)簽里面有文本 "About elk"。

請注意文本節(jié)點中的特殊字符:

  • 換行符:???(在 JavaScript 中為 ?\n?)
  • 空格:???

空格和換行符都是完全有效的字符,就像字母和數(shù)字。它們形成文本節(jié)點并成為 DOM 的一部分。所以,例如,在上面的示例中,<head> 標(biāo)簽中的 <title> 標(biāo)簽前面包含了一些空格,并且該文本變成了一個 #text 節(jié)點(它只包含一個換行符和一些空格)。

只有兩個頂級排除項:

  1. 由于歷史原因,?<head>? 之前的空格和換行符均被忽略。
  2. 如果我們在 ?</body>? 之后放置一些東西,那么它會被自動移動到 ?body? 內(nèi),并處于 ?body? 中的最下方,因為 HTML 規(guī)范要求所有內(nèi)容必須位于 ?<body>? 內(nèi)。所以 ?</body>? 之后不能有空格。

在其他情況下,一切都很簡單 —— 如果文檔中有空格(就像任何字符一樣),那么它們將成為 DOM 中的文本節(jié)點,而如果我們刪除它們,則不會有任何空格。

這是沒有空格的文本節(jié)點:

<!DOCTYPE HTML>
<html><head><title>About elk</title></head><body>The truth about elk.</body></html>


字符串開頭/結(jié)尾處的空格,以及只有空格的文本節(jié)點,通常會被工具隱藏

與 DOM 一起使用的瀏覽器工具(即將介紹)通常不會在文本的開始/結(jié)尾顯示空格,并且在標(biāo)簽之間也不會顯示空文本節(jié)點(換行符)。

開發(fā)者工具通過這種方式節(jié)省屏幕空間。

在本教程中,如果這些空格和空文本節(jié)點無關(guān)緊要時,我們在后面出現(xiàn)的關(guān)于 DOM 的示意圖中會忽略它們。這樣的空格通常不會影響文檔的顯示方式。

自動修正

如果瀏覽器遇到格式不正確的 HTML,它會在形成 DOM 時自動更正它。

例如,頂級標(biāo)簽總是 <html>。即使它不存在于文檔中 — 它也會出現(xiàn)在 DOM 中,因為瀏覽器會創(chuàng)建它。對于 <body> 也是一樣。

例如,如果一個 HTML 文件中只有一個單詞 “Hello”,瀏覽器則會把它包裝到 <html> 和 <body> 中,并且會添加所需的 <head>,DOM 將會變成下面這樣:


在生成 DOM 時,瀏覽器會自動處理文檔中的錯誤,關(guān)閉標(biāo)簽等。

一個沒有關(guān)閉標(biāo)簽的文檔:

<p>Hello
<li>Mom
<li>and
<li>Dad

……將成為一個正常的 DOM,因為瀏覽器在讀取標(biāo)簽時會填補缺失的部分:


表格永遠(yuǎn)有 ?<tbody>?

表格是一個有趣的“特殊的例子”。按照 DOM 規(guī)范,它們必須具有 <tbody> 標(biāo)簽,但 HTML 文本可能會忽略它。然后瀏覽器在創(chuàng)建 DOM 時,自動地創(chuàng)建了 <tbody>。

對于 HTML:

<table id="table"><tr><td>1</td></tr></table>

DOM 結(jié)構(gòu)會變成:


看到了嗎?<tbody> 出現(xiàn)了。我們應(yīng)該記住這一點,以免在使用表格時,對這種情況感到驚訝。

其他節(jié)點類型

除了元素和文本節(jié)點外,還有一些其他的節(jié)點類型。

例如,注釋:

<!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>


在這里我們可以看到一個新的樹節(jié)點類型 —— comment 節(jié)點,被標(biāo)記為 #comment,它在兩個文本節(jié)點之間。

我們可能會想 —— 為什么要將注釋添加到 DOM 中?它不會對視覺展現(xiàn)產(chǎn)生任何影響嗎。但是有一條規(guī)則 —— 如果一些內(nèi)容存在于 HTML 中,那么它也必須在 DOM 樹中。

HTML 中的所有內(nèi)容,甚至注釋,都會成為 DOM 的一部分。

甚至 HTML 開頭的 <!DOCTYPE...> 指令也是一個 DOM 節(jié)點。它在 DOM 樹中位于 <html> 之前。很少有人知道這一點。我們不會觸及那個節(jié)點,我們甚至不會在圖表中繪制它,但它確實就在那里。

表示整個文檔的 document 對象,在形式上也是一個 DOM 節(jié)點。

一共有 12 種節(jié)點類型。實際上,我們通常用到的是其中的 4 種:

  1. ?document? —— DOM 的“入口點”。
  2. 元素節(jié)點 —— HTML 標(biāo)簽,樹構(gòu)建塊。
  3. 文本節(jié)點 —— 包含文本。
  4. 注釋 —— 有時我們可以將一些信息放入其中,它不會顯示,但 JS 可以從 DOM 中讀取它。

自己看看

要在實際中查看 DOM 結(jié)構(gòu),請嘗試 Live DOM Viewer。只需輸入文檔,它將立即顯示為 DOM。

探索 DOM 的另一種方式是使用瀏覽器開發(fā)工具。實際上,這就是我們在開發(fā)中所使用的。

你可以打開這個網(wǎng)頁 elks.html,然后打開瀏覽器開發(fā)工具,并切換到元素(Elements)選項卡。

它看起來像這樣:


你可以看到 DOM,點擊元素,查看它們的細(xì)節(jié)等。

請注意,開發(fā)者工具中的 DOM 結(jié)構(gòu)是經(jīng)過簡化的。文本節(jié)點僅以文本形式顯示。并且根本沒有“空白”(只有空格)的文本節(jié)點。這其實挺好,因為大多數(shù)情況下,我們只關(guān)心元素節(jié)點。

點擊左上角的按鈕可以讓我們使用鼠標(biāo)(或其他指針設(shè)備)從網(wǎng)頁中選擇一個節(jié)點并“檢查(inspect)”它(在元素選項卡中滾動到該節(jié)點)。當(dāng)我們有一個巨大的 HTML 頁面(和相應(yīng)的巨大 DOM),并希望查看其中的一個特定元素的位置時,這很有用。

另一種方法是在網(wǎng)頁上右鍵單擊,然后在上下文菜單中選擇“檢查(Inspect)”。


在工具的右側(cè)部分有以下子選項卡:

  • Styles —— 我們可以看到按規(guī)則應(yīng)用于當(dāng)前元素的 CSS 規(guī)則,包括內(nèi)建規(guī)則(灰色)。幾乎所有內(nèi)容都可以就地編輯,包括下面的方框的 dimension/margin/padding。
  • Computed —— 按屬性查看應(yīng)用于元素的 CSS:對于每個屬性,我們可以都可以看到賦予它的規(guī)則(包括 CSS 繼承等)。
  • Event Listeners —— 查看附加到 DOM 元素的事件偵聽器(我們將在本教程的下一部分介紹它們)。
  • ……等。

學(xué)習(xí)它們的最佳方式就是多點一點看一下。大多數(shù)值都是可以就地編輯的。

與控制臺交互

在我們處理 DOM 時,我們可能還希望對其應(yīng)用 JavaScript。例如:獲取一個節(jié)點并運行一些代碼來修改它,以查看結(jié)果。以下是在元素(Elements)選項卡和控制臺(Console)之間切換的一些技巧。

首先:

  • 在元素(Elements)選項卡中選擇第一個 ?<li>?。
  • 按下 ?Esc? —— 它將在元素(Elements)選項卡下方打開控制臺(Console)。

現(xiàn)在最后選中的元素可以通過 $0 來進(jìn)行操作,在之前的選擇中則是 $1。

我們可以對它們執(zhí)行一些命令。例如,$0.style.background = 'red' 使選定的列表項(list item)變成紅色,像這樣:


這就是在控制臺(Console)中獲取元素(Elements)選項卡中的節(jié)點的方法。

還有一種方式。如果存在引用 DOM 節(jié)點的變量,那么我們可以在控制臺(Console)中使用命令 inspect(node),來在元素(Elements)選項卡中查看它。

或者我們可以直接在控制臺(Console)中輸出 DOM 節(jié)點,并“就地”探索它,例如下面的 document.body


當(dāng)然,這是出于調(diào)試目的。從下一章開始,我們將使用 JavaScript 訪問和修改 DOM。

瀏覽器開發(fā)者工具對于開發(fā)有很大的幫助:我們可以探索 DOM,嘗試一些東西,并找出問題所在。

總結(jié)

HTML/XML 文檔在瀏覽器內(nèi)均被表示為 DOM 樹。

  • 標(biāo)簽(tag)成為元素節(jié)點,并形成文檔結(jié)構(gòu)。
  • 文本(text)成為文本節(jié)點。
  • ……等,HTML 中的所有東西在 DOM 中都有它的位置,甚至對注釋也是如此。

我們可以使用開發(fā)者工具來檢查(inspect)DOM 并手動修改它。

在這里,我們介紹了基礎(chǔ)知識,入門最常用和最重要的行為。在 https://developers.google.cn/web/tools/chrome-devtools 上有關(guān)于 Chrome 開發(fā)者工具的詳細(xì)文檔說明。學(xué)習(xí)這些工具的最佳方式就是到處點一點看一看,閱讀菜單:大多數(shù)選項都很明顯。而后,當(dāng)你大致了解它們后,請閱讀文檔并學(xué)習(xí)其余內(nèi)容。

DOM 節(jié)點具有允許我們在它們之間移動,修改它們,在頁面中移動等的屬性和方法。在下一章中,我們將介紹它們。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號