【譯】到底什麼是DOM

好好學習努力造輪子發表於2019-01-03

The Document Object Model(文件物件模型), 或者叫DOM,是網頁的介面。它本質上是網頁的API,允許程式讀取和操作頁面內容,結構和樣式。接下來讓我們進一步解析。

一個網頁是如何構建的

一個瀏覽器如何從HTML源文件到視窗中展現樣式和互動式頁面的過程被稱為“關鍵渲染路徑(Critical Rendering Path)”,雖然這個過程可以被分解為多個步驟, 但是這些步驟大致可以分為兩個階段。第一個階段涉及瀏覽器解析文件到最終確認渲染的內容,第二階段則是瀏覽器執行渲染。

render tree

第一階段的結果被稱之為“渲染樹(render tree)”。HTML元素及其相關樣式在頁面上呈現出來的表達形式被稱之為渲染樹。為了構建樹結構,瀏覽器需要兩個東西:

  1. The CSSOM, 與元素相關的樣式表達(譯者: 就是css文件)
  2. DOM, 元素表達 (譯者: 就是HTML文件)

DOM如何被創造出來(看起來什麼樣)

DOM是源HTML文件基於物件的表現形式。它有些差異,但是它本質上是將HTML文件的結構和內容轉化為可以被各種程式使用的一種物件模型。

DOM的物件結構表現為所謂的“節點樹(node tree)”,它之所以被這麼叫是因為它可以被看作一個單個父莖的樹,其有著若干個分支,每個都可能有枝葉。在這種情況下,父“幹”是根元素,孩子“分支”是巢狀元素,而“葉”是元素中的內容。

來看看一下這個例子:

<!doctype html>
<html lang="en">
 <head>
   <title>My first web page</title>
  </head>
 <body>
    <h1>Hello, world!</h1>
    <p>How are you?</p>
  </body>
</html>
複製程式碼

以上文件的節點樹表達形式:

example 1 node tree

DOM 不是什麼

根據上述例子,DOM是源HTML文件的一對一對映。 但是,正如我所提到的,還是有差異的。 為了完全理解DOM是什麼,我們需要看看它不是什麼。

DOM不是你的原始碼

儘管DOM是從源HTML文件建立的,但它並不總是完全相同。 這裡有兩個例項展示了:DOM可以與源HTML不同。

1. 當HTML無效時

DOM是有效HTML文件的介面。在建立DOM的過程中,瀏覽器可能會矯正HTML中的無效程式碼。

例子:

<!doctype html>
<html>
Hello, world!
</html>
複製程式碼

上述文件中缺失<head><body>元素,對於有效HTML來說這是必需的。如果我們檢視生成的DOM樹,我們會發現這裡被自動矯正了:

example 2 node tree

2. 當JavaScript修改DOM時

DOM除了作為檢視HTML文件內容的介面之外,還可以被修改,使其成為一個實時資源。

例如,我們可以使用JavaScript為DOM建立其他節點。

var newParagraph = document.createElement("p");
var paragraphContent = document.createTextNode("I'm new!");
newParagraph.appendChild(paragraphContent);
document.body.appendChild(newParagraph);
複製程式碼

這樣就可以更新DOM, 但是當然並不是直接改變HTML文件

DOM並不是你在瀏覽器裡看到的那樣(例如: 渲染樹)

你在瀏覽器視窗中看到的渲染樹,正如我所提到,它是DOM和CSSOM的結合,真正把DOM和渲染樹區分開的是後者只包含最終將在螢幕上繪製的內容。

因為渲染樹僅僅關注與渲染的內容本身,所以它會排除視覺上隱藏的元素。比如:具有display: none的元素。

<!doctype html>
<html lang="en">
  <head></head>
  <body>
    <h1>Hello, world!</h1>
    <p style="display: none;">How are you?</p>
  </body>
</html>
複製程式碼

在DOM裡將包含<p>元素:

example 3 node tree

但是,渲染樹以及因此在視窗中看到的內容卻不包含該元素。

example 4 node tree

瀏覽器中的DOM並不是DOM

一點點小差異,因為DevTools元素檢查器提供了最接近的DOM。但是,DevTools檢查器包含裡不在DOM中的其他資訊。

最好的例子是CSS偽元素。Pseudo-elements created using the ::before and ::after selectors form part of the CSSOM and render tree, but are not technically part of the DOM.。因為DOM僅僅由源HTML文件構建,不包含應用於元素的樣式。

儘管偽元素不是DOM的一部分,但他們仍然在我們的DevTools元素檢查器中。

element inspector

這就是為什麼偽元素不能被JavaScript作為目標的原因,因為它們不是DOM的一部分。

總結

DOM是一個HTML文件的介面。它被瀏覽器用作確認在視窗中呈現內容的第一步,並通過Javascript程式來修改頁面的內容,結構,樣式。

雖然與其他形式的源HTML文件類似,但是DOM在許多方面還是有所不同:

  • 有效HTML(It is always valid HTML)
  • 可通過Javascript修改的實時模型(It is a living model that can be modified by JavaScript)
  • 不包含偽元素(It doesn't include pseudo-elements)
  • 包含隱藏元素(It does include hidden elements)

關於原文作者

原文是來自Ire Aderinokun發表在bitsofco.de上面的。

譯者語

工作學習前端兩年多,往往這些淺顯,基礎的知識最容易被忽略。Ire Aderinokun寫裡一系列DOM相關的文章,包括shadow DOM, Virtual DOM等等,我會爭取總翻譯出來。有時候我不會翻譯,或者感覺原文效果更好的,我就直接把原文po出來。

相關文章