官方定義——應用程序編程接口(API)
文檔對象模型是用於HTML和XML文檔的應用程序編程接口,它定義文檔的邏輯結構,以及訪問和操作文檔的方式。
"The Document Object Model (DOM) is an application programming interface (API) for HTML and XML documents. It defines the logical structure of documents and the way a document is accessed and manipulated." —— W3C DOM
“文檔對象模型是用於HTML和XML文檔的應用程序編程接口”
應用程序編程接口(Application Program Interface,簡稱API),就是“提供商”將一個功能的具體實現(業務邏輯)封裝起來,只暴露給“客戶”可供調用的編程接口。如果客戶想使用某一功能,則只需調用該功能對應的編程接口,而無需關注於具體實現。打個比方,海爾生產空調,你購買空調后按照說明書操作空調就好,不需要知道空調是根據什么原理造出來的。
對於DOM而言,“提供商”指的就是實現DOM的開發者(比如,開發JavaScript引擎V8的工程師),“客戶”指的就是使用DOM的開發者(比如,開發網站的前端工程師)。他們之間共同遵守的就是DOM規范。
因此,DOM規范同時約束它的實現者和使用者。DOM實現者必須實現規范中定義的所有接口,DOM使用者應該調用規范中相應的接口實現相應的功能。
如果你是實現者,需要關注如何實現DOM API;如果你是使用者,則只需關注如何使用DOM API。
“它定義文檔的邏輯結構,以及訪問和操作文檔的方式”
上面這句話對 DOM API 作了更具體的解釋,包括三層意思:
- 定義文檔的結構
- 訪問文檔的方式
- 操作文檔的方式
HTML DOM 是對 DOM Core 的擴展,添加了專門針對 HTML 文檔的特定對象和方法,它與現有的文檔對象模型一致。下面我們就來討論如何使用 HTML DOM API 的問題。
一、如何定義文檔的邏輯結構?——節點對象樹
DOM規范,將網頁中的HTML文檔抽象為內存中的節點對象樹(DOM Tree)。樹中的每一個節點對象對應HTML文檔中的一個元素。
二、如何訪問文檔?——訪問節點對象
(0) Document 接口作為文檔入口
Document 接口代表整個文檔。JavaScript 中的全局對象 document 是對 Document 接口的實現。
(1) 直接訪問文檔中的節點對象。
方法 | 描述 |
document.getElementsById("id"); | 通過 id 屬性獲取節點對象 |
document.getElementsByName("name"); | 通過 name 屬性獲取節點對象 |
document/element.getElementsByTagName("tag"); | 通過 tag 屬性獲取節點對象 |
document/element.getElementsByClassName("class1[ class2]"); | 通過 class 屬性獲取節點對象 |
document/element.querySelector("selector"); | 通過 css 選擇器 獲取首個節點對象 |
document/element.querySelectorAll("selector"); | 通過 css 選擇器 獲取所有節點對象 |
(2) 通過節點關系訪問一個節點周圍的節點對象。
關系 | 屬性 | 描述 |
父節點(parent node) | parentNode/parentElement | 獲取所屬父節點對象 |
ownerDocument | 獲取節點所屬文檔節點(根節點)對象 | |
兄弟節點(sibling nodes) | nextSibling nextElementSibling |
獲取前一個兄弟節點對象 獲取前一個兄弟元素節點對象 |
previousSibling previousElementSibling |
獲取后一個兄弟節點對象 獲取后一個兄弟元素節點對象 |
|
子節點(child nodes) | childNodes children |
獲取所有子節點對象 獲取所有子元素節點對象 |
hasChildNodes(); | 判斷是否包含子節點對象 | |
childElementCount | 獲取子元素節點對象數量 | |
firstChild firstElementChild |
獲取第一個子節點對象 獲取第一個子元素節點對象 |
|
lastChild lastElementChild |
獲取最后一個子節點對象 獲取最后一個子元素節點對象 |
三、如何操作文檔?——操作節點對象
思路一:【節點對象】首先是一個【對象】,只要是對象就具有【屬性】和【行為】。
元素節點p作為對象,id,class,style(該屬性是一個對象)等作為對象的屬性,onclick,onfocus,oninput 等作為對象的行為,具體的動作由 JavaScript 代碼控制。
思路二:節點對象只包含屬性 —— 特性屬性、樣式屬性和行為(事件)屬性。
將【行為】看作對象的一種屬性,以下實例印證了這一觀點:
我們獲取節點對象的目的,就是為了操作節點對象本身以及節點對象的屬性。
(0) 操作節點對象本身
操作 | 方法 | 描述 |
創建節點 | document.createElement("TAG"); document.createTextNode("#文本"); document.createComment("#注釋"); document.createDocumentFragment(); document.createAttribute("myAttrName"); |
創建一個元素節點 創建一個文本節點 創建一個注釋節點 創建一個空白的文檔片段節點 |
插入節點 | parentNode.appendChild(newChild); parentNode.insertBefore(newChild,refChild); |
插入子節點(作為最后子節點) 插入子節點(在指定子節點之前) |
刪除節點 | parentNode.removeChild(oldChild); | 刪除指定的子節點 |
替換節點 | parentNode.replaceChild(newChild,oldChild); | 替換一個子節點 |
克隆節點 | node.cloneNode(deep); | 克隆一個節點 |
(1) 操作節點對象的特性屬性
方法 | 描述 |
e.特性名稱[="value"]; | 獲取/設置特性值 |
e.getAttributeNames(); | 獲取已設置的全部屬性名稱(非IE內核) |
e.getAttribute("特性名稱"); | 獲取特性值 |
e.getAttributeNode("特性名稱"); | 獲取特性節點[特性名稱=特性值] |
e.setAttribute("特性名稱","特性值"); | 設置特性值(不存在時新建該屬性) |
e.setAttributeNode(Attr); |
(2) 操作節點對象的樣式屬性
方法 | 描述 |
e.style.color[ ="顏色值"] | 獲取/設置標簽內樣式(內嵌樣式) |
window.getComputedStyle(e).color; document.defaultView.getComputedStyle(e).color; |
獲取包括內嵌樣式、<style>、<link>在內的最終樣式(非IE內核 或 IE>8) |
e.currentStyle.color | 獲取包括內嵌樣式、<style>、<link>在內的最終樣式(IE內核) |
(3) 操作節點對象的行為(事件)屬性
方法 | 描述 |
e.onclick[ =fun()]; e.onclick(); |
獲取/設置事件 觸發事件 |
e.addEventListener("type",listener,[useCapture]); | 注冊事件(非IE內核 或 IE>8) |
e.attachEvent("ontype",listener); | 注冊事件(IE內核<11) |
e.removeEventListener("type",listener,[useCapture]); | 移除事件(非IE內核 或 IE>8) |
e.detachEvent("ontype",listener); | 移除事件(IE內核<11) |
e.dispatchEvent(event) | 調度(觸發)事件 |
(4) 操作節點對象的內容(屬性)
節點對象的內容,實際上是節點對象的子節點。傳統的方法是使用新創建的子節點替換需要修改的舊子節點。
<html> <body> <div> <p>第一個段落</p> <p>第二個段落</p> </div> </body> </html>
<script> //獲取父節點 var d = document.querySelector("div"); //獲取需要替換的舊子節點 var oldChild = d.firstChild; //創建新子節點 var newChild = document.createTextNode("新的文本"); //替換 d.replaceChild(newChild ,oldChild ); </script>
如此常用的操作,卻有如此繁瑣的操作過程,況且一次只能替換一個子節點,這也太坑了吧!別急,DOM 規范為我們提供了更加簡便的操作。
轉換一下思路,我們將節點對象的內容看作是節點對象的一個屬性。那么方法 e.innerHTML 屬性將以字符串的形式返回所有節點對象的內容。 e.innerHTML = newStr 將替換該內容。newStr 可以包含tag,替換的內容會自動轉換為節點對象(其實簡單的文本字符串,也會轉換成一個文本節點)。
<script> //獲取節點 var d = document.querySelector("div"); //修改節點內容 var str = "新的文本"; d.innerHTML= str; </script>
最終的節點對象應該是下面這張圖:
【The End】