Javascript DOM 樹

2023-02-17 10:54 更新

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

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

所有這些對(duì)象都可以通過(guò) JavaScript 來(lái)訪問(wèn),我們可以使用它們來(lái)修改頁(yè)面。

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

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

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

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

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

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

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

DOM 的例子

讓我們從下面這個(gè)簡(jiǎn)單的文檔(document)開始:

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

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


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

每個(gè)樹的節(jié)點(diǎn)都是一個(gè)對(duì)象。

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

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

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

請(qǐng)注意文本節(jié)點(diǎn)中的特殊字符:

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

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

只有兩個(gè)頂級(jí)排除項(xiàng):

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

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

這是沒(méi)有空格的文本節(jié)點(diǎn):

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


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

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

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

在本教程中,如果這些空格和空文本節(jié)點(diǎn)無(wú)關(guān)緊要時(shí),我們?cè)诤竺娉霈F(xiàn)的關(guān)于 DOM 的示意圖中會(huì)忽略它們。這樣的空格通常不會(huì)影響文檔的顯示方式。

自動(dòng)修正

如果瀏覽器遇到格式不正確的 HTML,它會(huì)在形成 DOM 時(shí)自動(dòng)更正它。

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

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


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

一個(gè)沒(méi)有關(guān)閉標(biāo)簽的文檔:

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

……將成為一個(gè)正常的 DOM,因?yàn)闉g覽器在讀取標(biāo)簽時(shí)會(huì)填補(bǔ)缺失的部分:


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

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

對(duì)于 HTML:

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

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


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

其他節(jié)點(diǎn)類型

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

例如,注釋:

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


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

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

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

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

表示整個(gè)文檔的 document 對(duì)象,在形式上也是一個(gè) DOM 節(jié)點(diǎn)。

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

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

自己看看

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

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

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

它看起來(lái)像這樣:


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

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

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

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


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

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

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

與控制臺(tái)交互

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

首先:

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

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

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


這就是在控制臺(tái)(Console)中獲取元素(Elements)選項(xiàng)卡中的節(jié)點(diǎn)的方法。

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

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


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

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

總結(jié)

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

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

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

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

DOM 節(jié)點(diǎn)具有允許我們?cè)谒鼈冎g移動(dòng),修改它們,在頁(yè)面中移動(dòng)等的屬性和方法。在下一章中,我們將介紹它們。


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)