翻譯:瘋狂的技術宅 原文:www.valentinog.com/blog/dom/
JavaScript 並沒有那麼糟糕。作為執行在瀏覽器中的指令碼語言,它對於網頁操作非常有用。在本文中,我們將看到可以用哪些手段來修改 HTML 文件和互動。
什麼是文件物件模型?
文件物件模型是在瀏覽器中一切的基礎。但它究竟是什麼呢?
當我們訪問網頁時,瀏覽器會計算出如何解釋每個 HTML 元素。這樣它就可以建立 HTML 文件的虛擬表示,並儲存在記憶體中。 HTML 頁面被轉換為樹狀結構並且每個 HTML 元素都變成一個葉子結點,連線到父分支。看一下這個簡單的 HTML 頁面:
<!DOCTYPE html>
<html lang="en">
<head>
<title>A super simple title!</title>
</head>
<body>
<h1>A super simple web page!</h1>
</body>
</html>
複製程式碼
在這個結構的頂部有一個文件,也稱為根元素,它包含另一個元素:html。 html 元素包含一個 head ,而 head 內又有一個 title。然後 body 中包含一個 h1。每個 HTML 元素都由特定型別(也稱為介面)表示,並且可以包含文字或其他巢狀元素:
document (HTMLDocument)
|
| --> html (HTMLHtmlElement)
|
| --> head (HtmlHeadElement)
| |
| | --> title (HtmlTitleElement)
| | --> text: "A super simple title!"
|
| --> body (HtmlBodyElement)
| |
| | --> h1 (HTMLHeadingElement)
| | --> text: "A super simple web page!"
複製程式碼
每個HTML元素都來自 Element,但其中很大一部分都是專用的。你可以通過檢查原型以查詢元素所屬的“種類”。例如,h1元素是 HTMLHeadingElement:
document.querySelector('h1').__proto__
// Output: HTMLHeadingElement
複製程式碼
而 HTMLHeadingElement 又是 HTMLElement 的“後代”:
document.querySelector('h1').__proto__.__proto__
// Output: HTMLElement
複製程式碼
這時(特別是初學者)可能會對 document 和 window 之間的區別產生一些混淆。讓我們看看它們有什麼不同!
window和document之間的區別
window 是指瀏覽器,而 document 是你當前正在操作的 HTML 頁面,即當前文件。文件介面有許多實用功能,比如 querySelector()
,一種用於選擇給定頁面內任何 HTML 元素的方法:
document.querySelector('h1');
複製程式碼
window 表示當前視窗的瀏覽器,以下程式碼效果與上述相同:
window.document.querySelector('h1');
複製程式碼
無論如何,以下語法更常見,你還會看到更多:
document.methodName();
複製程式碼
DOM 操作
DOM中的每個 HTML 元素也都是“節點”,實際上我們可以像這樣去檢查節點型別:
document.querySelector('h1').nodeType;
複製程式碼
上面的程式碼會返回 1,它是 Element 型別的節點的識別符號。你還可以檢查節點名稱:
document.querySelector('h1').nodeName;
"H1"
複製程式碼
上面的例子用大寫的形式返回節點名稱。需要理解的也是最重要的概念是,我們主要使用 DOM 中的兩種型別的節點:
- Element 型別的節點(HTML 元素)
- Text 型別的節點(文字節點)
為了建立 Element 型別的新節點,本機 DOM API 為我們提供了 createelement
方法,你通常會這樣呼叫:
var heading = document.createElement('h1');
複製程式碼
為了建立文字,我們可以用 createTextNode
:
var text = document.createTextNode('Hello world');
複製程式碼
通過在新的 HTML 元素中附加文字,可以將兩個節點組合在一起。最後需要注意的是,我們還可以將標題元素附加到根文件:
var heading = document.createElement('h1');
var text = document.createTextNode('Hello world');
heading.appendChild(text);
document.body.appendChild(heading);
複製程式碼
在瀏覽器中使用 JavaScript 時,你需要了解這三種方法。在技術圈中,我們將這些指令稱為 DOM 操作。
當以這種方式建立和操作元素時,我們談論的是“命令式” DOM操作。現代前端庫正在通過支援“宣告”方法來解決這個問題。我們不是一步一步地去命令瀏覽器,而是宣告我們需要什麼 HTML 元素,而庫可以處理剩下的部分。
DOM 操作和 jQuery
此時你可能會想:“我可以只使用jQuery嗎?為什麼要用 createElement
?“ 我經常會被問到這些問題。
好吧,請注意 jQuery 正逐漸消失。 Bootstrap 5 將從依賴項中刪除它,還有更多的庫或框架正在刪除它。這背後有一個十分正當的理由:原生 DOM API 已經非常完整且成熟到足以使 jQuery 過時。
如果你想堅持用原生 JavaScript 實現簡單的互動和操作。甚至可以建立自己的迷你框架來抽象出最常見的操作:建立元素、追加、建立文字等。
結論
文件物件模型是瀏覽器建立並保留在記憶體中的網頁的虛擬副本。在建立、修改、刪除 HTML 元素時,我們會碰到 “DOM 操作”。在過去即使對於更簡單的任務,我們也要依賴於 jQuery,但今天本機 API 已經互相相容並且足夠成熟以使 jQuery 過時。
雖然 jQuery 不會很快的消失,但每個 JavaScript 程式設計師都必須知道該如何使用本機 API 去操作 DOM。這樣做有很多理由,其他庫會增加 JavaScript 程式的載入時間和大小,更不用說 DOM 操作在技術面試中出現的越來越多。
DOM 中可用的每 個HTML 元素都有一個暴露一定數量屬性和方法的介面。如果對使用什麼方法有疑問,可以參考 MDN上的優秀文件。
操作 DOM 最常用的方法是 document.createElement()
用於建立新的 HTML 元素,document.createTextNode()
用於在 DOM 內建立文字節點。需要注意的是 .appendChild()
用於將新的 HTML 元素或文字節點附加到現有元素。
雖然很好的瞭解本機 API 是很好的,但是現代前端庫也提供了無可置疑的好處。儘管用“原生” JavaScript 去構建大型JavaScript 程式確實是可行的,但有時 Angular、React、Vue可以提供很多幫助。僅使用 JavaScript 來處理更簡單的原型和中小型應用也是明智之舉。
資源
如果你想了解更多關於文件物件模型的內容,那麼 Aderinokun 還有另一篇好文章。非常詳細,值得一讀:文件物件模型究竟是什麼?
如果你想回到基礎知識,請檢視如何使用原生 JavaScript 生成表格 一文!在沒有任何前端框架的幫助的情況下,你會發現實現它都需要什麼。