The Document Object Model(文件物件模型), 或者叫DOM,是網頁的介面。它本質上是網頁的API,允許程式讀取和操作頁面內容,結構和樣式。接下來讓我們進一步解析。
一個網頁是如何構建的
一個瀏覽器如何從HTML源文件到視窗中展現樣式和互動式頁面的過程被稱為“關鍵渲染路徑(Critical Rendering Path)”,雖然這個過程可以被分解為多個步驟, 但是這些步驟大致可以分為兩個階段。第一個階段涉及瀏覽器解析文件到最終確認渲染的內容,第二階段則是瀏覽器執行渲染。
第一階段的結果被稱之為“渲染樹(render tree)”。HTML元素及其相關樣式在頁面上呈現出來的表達形式被稱之為渲染樹。為了構建樹結構,瀏覽器需要兩個東西:
- The CSSOM, 與元素相關的樣式表達(譯者: 就是css文件)
- 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>
複製程式碼
以上文件的節點樹表達形式:
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樹,我們會發現這裡被自動矯正了:
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>
元素:
但是,渲染樹以及因此在視窗中看到的內容卻不包含該元素。
瀏覽器中的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元素檢查器中。
這就是為什麼偽元素不能被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出來。