原生DOM接口挺多的,須要花點時間研究下,不過先把基礎整好,後面框架估計好學點。javascript
先回顧一下HTML的基本結構html
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
</head>
<body>
</body>
</html>
複製代碼
以上就是最簡單的HTML 5的結構。通常咱們會把它處理成一棵樹,一棵節點樹。java
以上就是一棵樹,瀏覽器把html渲染成的樹,也就是Document結構。每一個框就是一個Element、標題等文本內容是Text。node
Document、Element、Text 的祖先都是Node。 如下是MDN的繼承樹編程
但是在內存中,存的不是html樹,是一棵對應html各個節點的對象樹,並且對象樹的節點是與html樹的節點一一對應的。數組
以上是內存中的對象樹。這些對象應該怎麼定義,是由DOM規範規定的。瀏覽器
也能夠以下這麼理解bash
頁面中的節點,根據Element、Text、Document、Comment這些構造函數,構造出對象來,內存就理解了。app
好比構造div框架
var div = document.createElement('div')
undefined
div
<div></div> //打印結果
複製代碼
createElement
就是構造函數。
把DOM的對應和JS基本語法練習起來。
前面的基礎分析完了,就能夠知道什麼是DOM了。
DOM就是完整的把Document和Object映射到一塊兒,符合DOM規範的結構,因此具有不少的API。
DOM 是 JavaScript 操做網頁的接口,全稱爲「文檔對象模型」(Document Object Model)。它的做用是將網頁轉爲一個 JavaScript 對象,從而能夠用腳本進行各類操做(好比增刪內容)。
瀏覽器會根據 DOM 模型,將結構化文檔(好比 HTML 和 XML)解析成一系列的節點,再由這些節點組成一個樹狀結構(DOM Tree)。全部的節點和最終的樹狀結構,都有規範的對外接口。因此,DOM 能夠理解成網頁的編程接口。DOM 有本身的國際標準,目前的通用版本是DOM 3,下一代版本DOM 4正在擬定中。
嚴格地說,DOM 不屬於 JavaScript,可是操做 DOM 是 JavaScript 最多見的任務,而 JavaScript 也是最經常使用於 DOM 操做的語言。
規範裏的DOM模型居然有多達31個接口,我先只挑Node接口和Document接口學習。
DOM是一棵樹,樹上有Node,Node分爲Document、Element、Text,其餘的能夠忽略。
由前面的繼承圖可知Node的研究價值很高,咱們先來看Node接口的屬性和方法。 下面是MDN對Node接口的解釋
Node是一個接口,許多DOM類型從這個接口繼承,並容許相似地處理(或測試)這些各類類型。
- 如下接口都從Node繼承其方法和屬性: Document, Element, CharacterData (which Text, Comment, and CDATASection inherit), ProcessingInstruction, DocumentFragment, DocumentType, Notation, Entity, EntityReference
DOM樹的最小單位就是節點(node)。文檔的樹形結構就是有各個不一樣列類型的節點組成的,每一個節點均可以看作是這棵DOM樹的葉子
常見的七種node類型
名字 | 做用 |
---|---|
Document | 整個文檔樹的頂層節點 但不是根節點 |
DocumentType | doctype標籤 |
Element | 網頁的其餘各類標籤 |
Attribute | 標籤的屬性 |
Text | 標籤與標籤之間的文本 |
Comment | 註釋 |
DocumentFragment | 文檔的片斷 |
咱們只關心Document、Element、Text
返回一個NodeList集合,成員包括當前節點的全部子節點。注意,除了HTML元素節點,該屬性返回的還包括Text節點和Comment節點。若是當前節點不包括任何子節點,則返回一個空的NodeList集合。因爲NodeList對象是一個動態集合,一旦子節點發生變化,馬上會反映在返回結果之中。
注意: childNodes會把text也打印出來,也就是兩個標籤之間的換行符。
並且childNodes返回一個僞數組。這個僞數組對象的每個元素依然都是html元素,若是想操做元素的內容還要用元素的其餘屬性。
document.childNodes
(2) [<!DOCTYPE html>, html] 0:<!DOCTYPE html> 1:html length:2 __proto__: NodeList 複製代碼
children
屬性啊ParentNode.children //ParentNode要是一個HTMLCollection
複製代碼
上述children屬性會返回 一個Node的子elements 而沒有text節點。
firstChild
屬性返回當前節點的第一個子節點,若是當前節點沒有子節點,則返回null
(注意,不是undefined
)。
Node.lastChild
屬性返回當前節點的最後一個子節點,若是當前節點沒有子節點,則返回null。
Node.nextSibling
屬性返回緊跟在當前節點後面的第一個同級節點。若是當前節點後面沒有同級節點,則返回null
。
previousSibling
屬性返回當前節點前面的、距離最近的一個同級節點。若是當前節點前面沒有同級節點,則返回null
。
以上的三組屬性使用時必定要注意結果會有text的影響。
document.parentNode
null
複製代碼
parentNode
屬性返回當前節點的父節點。對於一個節點來講,它的父節點只多是三種類型:element
節點、document
節點和documentfragment
節點。
並且document節點和documentfragment節點,它們的父節點都是null。另外,對於那些生成後還沒插入DOM樹的節點,父節點也是null。
parentElement屬性返回當前節點的父Element節點。若是當前節點沒有父節點,或者父節點類型不是Element節點,則返回null。
注意: 在IE瀏覽器中,只有Element節點纔有該屬性,其餘瀏覽器則是全部類型的節點都有該屬性。
ownerDocument
屬性返回當前節點所在的頂層文檔對象,即document
對象
nodeName返回node的名字,若是是element那名字是大寫的,其餘的名字前面寫上#。nodeType返回node的類型,通常用數字表示,1表示element(也能夠用Node.ELEMENT_NODE來表示),3表示text(Node.TEXT_NODE)。
關於nodeType有個詳細的表格,應該查看MDN記住。對照表
nodeValue屬性返回或設置當前節點的值。對於text, comment節點來講, nodeValue
返回該節點的文本內容,對於 attribute 節點來講, 返回該屬性的屬性值,而對於document和element節點來講,返回null。 貌似沒個卵用,最多見的element都是null,仍是用下面的textContent
吧
火狐推出的textContent,得到一個節點及其後代的文本內容,通常用這個得到元素的內容。
IE推出的innerText,二者有很大的區別。
關於textContent、innerText、innnerHTML之間的區別請看MDN
Node.appendChild()
方法將一個節點添加到指定父節點的子節點列表的末尾。
var child = node.appendChild(child);
node
是要插入子節點的父節點.child
便是參數又是這個方法的返回值.這個方法就是克隆一個node,分爲淺拷貝和深拷貝。
Node.cloneNode()
只克隆元素節點自己,而不會克隆它的子節點。包括它的文本節點Node.cloneNode(true)
克隆元素的全部屬性以及子節點注意:爲了防止一個文檔中出現兩個ID重複的元素,使用cloneNode()方法克隆的節點在須要時應該指定另一個與原ID值不一樣的ID
判斷一個節點是否是另外一個節點的子節點。
div.contains(div1)
複製代碼
div1是div的子節點就返回true。
div.hasChildNodes()
複製代碼
判斷div節點是否還有子節點,有子節點就返回true。
在當前節點的某個子節點以前再插入一個子節點。
var insertedElement = parentElement.insertBefore(newElement, referenceElement);
複製代碼
在parentElement節點的子節點referenceElement前面插入一個newElement節點。
若是referenceElement
爲null
則newElement
將被插入到子節點的末尾*。*若是newElement
已經在DOM樹中,newElement
首先會從DOM樹中移除。
沒有 insertAfter
方法。可使用 insertBefore
方法和 nextSibling
來模擬它。
parentDiv.insertBefore(sp1, sp2.nextSibling);
複製代碼
只要sp2.nextSibling === null,那麼就能夠在parentDiv的末尾添加sp1元素。
二者都是比較兩個node是否相等。不過isEqualNode()是兩個node看起來相等就返回true,isSameNode()嚴格使用===判斷,並且該方法已被廢棄,若是要嚴格判斷兩個node是否指向同一個對象,直接用node1 === node2。
就是規範化的意思。什麼是規範化,在一個"規範化"後的DOM樹中,不存在一個空的文本節點,或者兩個相鄰的文本節點。
var wrapper = document.createElement("div");
wrapper.appendChild(document.createTextNode("Part 1 "));
wrapper.appendChild(document.createTextNode("Part 2 "));
// 這時(規範化以前),wrapper.childNodes.length === 2
// wrapper.childNodes[0].textContent === "Part 1 "
// wrapper.childNodes[1].textContent === "Part 2 "
wrapper.normalize();
// 如今(規範化以後), wrapper.childNodes.length === 1
// wrapper.childNodes[0].textContent === "Part 1 Part 2"
複製代碼
以上是MDN的例子,很好懂。
以上是本身模仿的demo
Node.removeChild()是從當前節點刪除一個子節點,不過內存裏面依然存在,只不過不在頁面顯示了,返回的就是被移除的那個節點。因此說一個節點移除之後,依然可使用它,好比插入到另外一個節點下面。
以上是我作的demo
Node.replaceChild
方法用於將一個新的節點,替換掉當前節點的一個子節點。它接受兩個參數,第一個參數是用來替換的新節點,第二個參數將要被替換走的子節點。它返回被替換走的那個節點。
我作的實驗demo
關於Document接口的屬性和方法,且聽下回分解~