回到基礎:什麼是DOM及DOM操作?

前端小智發表於2019-12-18

譯者:前端小智

來源:valentinog

點贊再看,養成習慣


本文 GitHub:github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了很多我的文件,和教程資料。歡迎Star和完善,大家面試可以參照考點複習,希望我們一起有點東西。

個人專欄 ES6 深入淺出已上線,深入ES6 ,通過案例學習掌握 ES6 中新特性一些使用技巧及原理,持續更新中,←點選可訂閱。

文字主要介紹 **文件物件模型(DOM)**瞭解什麼是DOM操作,以及如何使用砶 DOM API 與 JS 中的 Web 頁面進行互動。

什麼是 DOM ?

DOM(文件物件模型)是針對於xml但是擴充套件用於HTML的應用程式程式設計介面,定義了訪問和操作HTML的文件的標準。

W3C文件物件模型是中立於平臺和語言之間的介面,它允許程式和指令碼動態的訪問和更新文件的內容、結構、樣式。總之HTML是關於如何獲取、修改、新增和刪除HTML元素的標準。

DOM 分層節點

DOM的分層節點一般被稱作是DOM樹,樹中的所有節點都可以通過指令碼語言例如JS進行訪問,所有HTMlL元素節點都可以被建立、新增或者刪除。

在DOM分層節點中,頁面就是用分層節點圖表示的。

  • 整個文件是一個文件節點,就想是樹的根一樣。
  • 每個HTML元素都是元素節點。
  • HTML元素內的文字就是文字節點。
  • 每個HTML屬性時屬性節點。

當我們們訪問一個web頁面時,瀏覽器會解析每個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>
複製程式碼

在這個結構的頂部有一個document,也稱為根元素,它包含另一個元素:htmlhtml元素包含一個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
複製程式碼

此時(特別是初學者)可能會對documentwindow之間的區別產生一些混淆。接下來看看它們有何不同!

document 和 window 之間的區別

簡單來說,documentwindow的一個物件屬性。window 物件表示瀏覽器中開啟的視窗。如果文件包含框架(frameiframe 標籤),瀏覽器會為 HTML 文件建立一個 window 物件,併為每個框架建立一個額外的 window 物件。所有的全域性函式和物件都屬於 window 物件的屬性和方法。

區別:

  1. window 指窗體。document指頁面。documentwindow的一個子物件。

  2. 使用者不能改變 document.location(因為這是當前顯示文件的位置)。但是,可以改變window.location (用其它文件取代當前文件)window.location本身也是一個物件,而document.location不是物件。

document介面有許多實用方法,比如querySelector(),它是用於查詢給定頁面內HTML元素的方法:

document.querySelector('h1');
複製程式碼

window表示當前的瀏覽器,下面程式碼與上面等價:

window.document.querySelector('h1');
複製程式碼

當然,更常見的是用第一種方式。

window是一個全域性物件,可以從瀏覽器中執行的任何JS程式碼直接訪問。 window暴露了很多屬性和方法,如:

window.alert('Hello world'); // Shows an alert
window.setTimeout(callback, 3000); // Delay execution
window.fetch(someUrl); // make XHR requests
window.open(); // Opens a new tab
window.location; // Browser location
window.history; // Browser history
window.navigator; // The actual user agent
window.document; // The current page
複製程式碼

因為這些屬性和方法也是全域性的,所以也可以這樣訪問它們

alert('Hello world'); // Shows an alert
setTimeout(callback, 3000); // Delay execution
fetch(someUrl); // make XHR requests
open(); // Opens a new tab
location; // Browser location
history; // Browser history
navigator; // The actual user agent
document;// The current page
複製程式碼

其中有些我們們都已經很熟悉了,如setTimeout() 的方法。 例如,當我們們想要得知當前使用者的瀏覽器語言時,window.navigator就非常有用:

if (window.navigator) {
  var lang = window.navigator.language;
  if (lang === "en-US") {
    // show something
  }

  if (lang === "it-IT") {
    // show something else
  }
}
複製程式碼

DOM 常用方法

獲取節點

// 通過id號來獲取元素,返回一個元素物件
document.getElementById(idName) 
      
// 通過name屬性獲取id號,返回元素物件陣列 
document.getElementsByName(name)  
   
// 通過class來獲取元素,返回元素物件陣列
document.getElementsByClassName(className)   

// 通過標籤名獲取元素,返回元素物件陣列
document.getElementsByTagName(tagName)       
複製程式碼

獲取/設定元素的屬性值:

// 括號傳入屬性名,返回對應屬性的屬性值
element.getAttribute(attributeName)

// 傳入屬性名及設定的值
element.setAttribute(attributeName,attributeValue)
複製程式碼

建立節點Node

// 建立一個html元素,這裡以建立h3元素為例
document.createElement("h3")

// 建立一個文字節點;
document.createTextNode(String);

// 建立一個屬性節點,這裡以建立class屬性為例
document.createAttribute("class");
複製程式碼

增添節點

// 往element內部最後面新增一個節點,引數是節點型別
element.appendChild(Node);

// 在element內部的中在existingNode前面插入newNode
elelment.insertBefore(newNode,existingNode); 
複製程式碼

刪除節點

//刪除當前節點下指定的子節點,刪除成功返回該被刪除的節點,否則返回null
element.removeChild(Node)
複製程式碼

DOM常用屬性

獲取當前元素的父節點

// 返回當前元素的父節點物件
element.parentNode
複製程式碼

獲取當前元素的子節點

// 返回當前元素所有子元素節點物件,只返回HTML節點
element.chlidren

// 返回當前元素多有子節點,包括文字,HTML,屬性節點。(回車也會當做一個節點)
element.chilidNodes

// 返回當前元素的第一個子節點物件
element.firstChild

// 返回當前元素的最後一個子節點物件
element.lastChild
複製程式碼

獲取當前元素的同級元素

// 返回當前元素的下一個同級元素 沒有就返回null
element.nextSibling

// 返回當前元素上一個同級元素 沒有就返回 null
element.previousSibling
複製程式碼

獲取當前元素的文字

// 返回元素的所有文字,包括html程式碼
element.innerHTML

// 返回當前元素的自身及子代所有文字值,只是文字內容,不包括html程式碼
element.innerText
複製程式碼

獲取當前節點的節點型別

// 返回節點的型別,數字形式(1-12)
// 常見幾個1:元素節點,2:屬性節點,3:文字節點。
node.nodeType   
複製程式碼

設定樣式

// 設定元素的樣式時使用style
element.style.color=“#eea”;
複製程式碼

DOM 操作

DOM中的每個HTML元素也是一個節點,可以像這樣查詢節點:

document.querySelector('h1').nodeType;
複製程式碼

上面會返回1,它是Element型別的節點的識別符號,還可以檢查節點名稱:

document.querySelector('h1').nodeName;

"H1"
複製程式碼

上面的示例返回大寫的節點名。但是需要理解的最重要的概念是,我們們主要使用DOM中的兩種型別的節點:

  • 元素節點
  • 文字節點

建立元素節點,可以通過 createElement方法:

var heading = document.createElement('h1');
複製程式碼

建立文字節點,可能通過 createTextNode 方法:

var text = document.createTextNode('Hello world');
複製程式碼

接著將兩個節點組合在一起,然後新增到 body 上:

var heading = document.createElement('h1');
var text = document.createTextNoe('Hello world');
heading.appendChild(text);
document.body.appendChild(heading)
複製程式碼

在學習Dom操作時候,這些方法需要牢記並熟練使用的。

目前像我們們用這種方式建立和操作元素,是屬於命令式DOM操作。現代前端庫通過支援宣告性方法來解決這個問題,如 JQuery,我們們可以宣告需要什麼HTML元素,其它就由庫來完成。

DOM 操作和 jQuery

大部分可能會想,我們們直接使用 JQ 不就行了,為啥還要用如createElement這些原生的方法,多費勁。

請注意jQuery正在漸漸消失。Bootstrap 5將把它從依賴項中刪除,還有很多專案也在刪除它。這背後有一個合理的原因:原生DOM API提供了大量像JQ這樣操作DOM的簡便方法,足以替代jQuery一些常用的DOM操作。

如果只是想進行簡單的互動和操作,請使用普通的JS。我們們甚至可以建立自己的迷你框架來抽象最常見的操作:建立元素、追加、建立文字。

總結

DOM是瀏覽器建立並保留在記憶體中的網頁的虛擬副本。建立、修改、刪除 HTML 元素,這些屬於 “DOM 操作”。在過去即使對於更簡單的任務,我們們也要依賴於 jQuery,但今天原生 API 已經互相相容並且足夠成熟足以替代 jQuery 了。

jQuery不會很快消失,但是每個JS開發人員都必須知道如何使用原生API操作DOM。這樣做有很多原因,額外的庫增加了JS應用程式的載入時間和大小,更不用說DOM操作在技術面試也經常出現。

操作 DOM 最常用的方法是 document.createElement() 用於建立新的 HTML 元素,document.createTextNode() 用於在 DOM 內建立文字節點。需要注意的是 .appendChild() 用於將新的 HTML 元素或文字節點附加到現有元素。

雖然很好的瞭解本機 API 是很好的,但是現代前端庫也提供了無可置疑的好處。儘管用“原生” JS 去構建大型JS 程式確實是可行的,但有時 Angular、React、Vue可以提供很多幫助。僅使用 JavaScript 來處理更簡單的原型和中小型應用也是明智之舉。

原文:www.valentinog.com/blog/html-t…

程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

交流

乾貨系列文章彙總如下,覺得不錯點個Star,歡迎 加群 互相學習。

github.com/qq449245884…

因為篇幅的限制,今天的分享只到這裡。如果大家想了解更多的內容的話,可以去掃一掃每篇文章最下面的二維碼,然後關注我們們的微信公眾號,瞭解更多的資訊和有價值的內容。

回到基礎:什麼是DOM及DOM操作?

相關文章