JavaScript DOM 總結(一)
DOM 是 Document Object Model(文件物件模型)的縮寫。DOM 描繪了一個層次化的節點樹,允許開發人員新增、移除和修改頁面的某一部分。 HTML DOM 樹形結構如下:
DOM 可以將任何 HTML 或 XML 文件描繪成一個由多層節點構成的結構。節點分為幾種不同的型別,每種型別分別表示文件中不同的資訊及(或)標記。每個節點都擁有各自的特點、資料和方法,另外也與其他節點存在某種關係。
Node型別屬性
DOM1 級定義了一個 Node 介面,該介面將由 DOM 中的所有節點型別實現。JavaScript 中的所有節點型別都繼承自 Node 型別,因此所有節點型別都共享著相同的基本屬性和方法。每個節點都有nodeType 、nodeName 和 nodeValue 屬性。
nodeType屬性:用於表明節點的型別。Node型別定義了12個常量值來表示不同節點型別,具體如下:
- Node.ELEMENT_NODE(1);
- Node.ATTRIBUTE_NODE(2);
- Node.TEXT_NODE(3);
- Node.CDATA_SECTION_NODE(4);
- Node.ENTITY_REFERENCE_NODE(5);
- Node.ENTITY_NODE(6);
- Node.PROCESSING_INSTRUCTION_NODE(7);
- Node.COMMENT_NODE(8);
- Node.DOCUMENT_NODE(9);
- Node.DOCUMENT_TYPE_NODE(10);
- Node.DOCUMENT_FRAGMENT_NODE(11);
- Node.NOTATION_NODE(12)。
要了解節點的具體資訊,可以使用 nodeName 和 nodeValue 這兩個屬性。這兩個屬性的值完全取決於節點的型別。例如:元素節點的 nodeName 是標籤名稱,屬性節點的 nodeName 是屬性名稱;對於文字節點,nodeValue 屬性包含文字。對於屬性節點,nodeValue 屬性包含屬性值。nodeValue 屬性對於文件節點和元素節點是不可用的。
<!DOCTYPE html>
<html lang="en">
<head >
<meta charset="UTF-8">
<title>nodeType nodeName nodeValue屬性</title>
</head>
<body>
<div id="div1">div內文字</div>
</body>
<script type="text/javascript">
var div = document.getElementById("div1");
console.log(div.nodeType); // 1
console.log(div.nodeName); // DIV
console.log(div.nodeValue); // null
var textNode = div.childNodes[0];
console.log(textNode.nodeType); //3
console.log(textNode.nodeName); //#text
console.log(textNode.nodeValue); //div內文字
</script>
</html>
上述程式碼建立了一個div元素節點,元素節點的nodeType為1,nodeName為對應的節點名稱,nodeValue對元素節點不可用,因此為null。在div內還有一段文字,為文字節點,通過div.childNodes[0]可獲得,文字節點的nodeType為3,nodeName永遠是 #text,nodeValue 包含文字內容。
節點關係
HTML文件可以描述成HTML DOM樹,那麼DOM樹中的節點彼此擁有層級關係。父(parent)、子(child)和同胞(sibling)等術語用於描述這些關係。父節點擁有子節點。同級的子節點被稱為同胞(兄弟或姐妹)。節點之間的關係可以表述如下:
與節點層次關係有關的屬性
屬性 | 含義 |
---|---|
parentNode | 獲取該節點的父節點 |
childNodes | 獲取該節點的子節點陣列 |
firstChild | 獲取該節點的第一個子節點 |
lastChild | 獲取該節點的最後一個子節點 |
nextSibling | 獲取該節點的下一個兄弟節點 |
previousSibling | 獲取該節點的上一個兄弟節點 |
為了解釋上述屬性的具體含義,下面通過具體程式碼實現。首先建立HTML文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM樹節點層次關係</title>
</head>
<body>
<div id="father">
<p id="child1">child1</p>
<p id="child2">child2</p>
<p id="child3">child3</p>
</div>
</body>
</html>
1、parentNode
var father = document.getElementById("father");
var child1 = document.getElementById("child1");
var child2 = document.getElementById("child2");
var child3 = document.getElementById("child3");
console.log(child1.parentNode.nodeName); //DIV
console.log(child1.parentNode===child2.parentNode); // true
獲取id為child1的p元素的parentNode為DIV,child2和child1的parentNode為同一個。
2、childNodes
var nodelist = father.childNodes;
console.log(nodelist.item(1).innerHTML); // child1
console.log(nodelist[1].innerHTML); // child1
console.log(nodelist.length); // 7
上述程式碼獲取div的childNodes,其中儲存著一個 NodeList 物件。 NodeList 是一種類陣列物件,用於儲存一組有序的節點,可以通過位置來訪問這些節點。上述程式碼第二行和第三行描述瞭如何獲取裡面的節點,可以通過方括號,也可以使用 item()方法。並且可以通過.length
來獲取 NodeList 物件中有幾個節點。
我們注意到div中只有三個P元素,為何通過.length
得到的結果是7呢?這是因為我們在寫HTML文件時存在換行空格,這些換行空格表示一個文字節點,我們可以通過for迴圈來遍歷NodeList 物件中的每一個節點:
for (var i = 0; i < nodelist.length; i++) {
// console.log(nodelist[i].nodeType);
if (nodelist[i].nodeType==1) {
console.log(nodelist[i].innerHTML);
}else{
console.log(nodelist[i].nodeType+":"+nodelist[i].nodeName+":("+nodelist[i].nodeValue+")");
}
}
在FireFox瀏覽器中得到的結果如下:
3、firstChild
firstChild即獲取某個節點的第一個子節點,要獲取第一個子節點也可以通過someNode.childNodes[0]或someNode.childNodes.item(0)獲取。
4、lastChild
lastChild即獲取某個節點的最後一個子節點,要獲取最後一個子節點也可以通過someNode.childNodes [someNode.childNodes.length-1]或者someNode.childNodes.item(someNode.childNodes.length-1)
5、nextSibling
nextSibling即獲取該節點的下一個兄弟節點,同一兄弟級節點中最後一個節點的 nextSibling 屬性的值為 null:
console.log(nodelist[0].nextSibling); // <p id="child1">
console.log(child1.nextSibling); //<TextNode textContent="\n ">
console.log(nodelist[nodelist.length-1].nextSibling); // null
6、previousSibling
previousSibling即獲取該節點的上一個兄弟節點,同一兄弟級節點中最後一個節點的 previousSibling屬性的值同樣為null:
console.log(nodelist[0].previousSibling); // null
console.log(child1.previousSibling); //<TextNode textContent="\n ">
console.log(nodelist[nodelist.length-1].previousSibling); // <p id="child3">
另外, hasChildNodes()也是一個非常有用的方法,這個方法在節點包含一或多個子節點的情況下返回 true;當然,也可以通過childNodes的length 屬性來判斷是否存在子節點。
元素節點
但是大部分情況下,我們都是需要對元素節點進行操作,對應的元素節點的屬性的如下:
屬性 | 含義 |
---|---|
children | 所有子元素節點 |
childElementCount | 子元素節點個數量 |
firstElementChild | 第一個子元素節點 |
lastElementChild | 最後一個子元素節點 |
nextElementSibling | 下一個兄弟元素節點 |
previousElementSibling | 前一個兄弟元素節點 |
上述的六個屬性只包含元素節點,不包含文字節點,因此可以避免我們在程式中出現的換行空格被當做文字節點的情況,以下還是以上述的DOM結構來測試這六個元素節點屬性。
var father = document.getElementById("father");
var child1 = document.getElementById("child1");
var child2 = document.getElementById("child2");
var child3 = document.getElementById("child3");
var childrenlist = father.children;
console.log(childrenlist.length); // 3
console.log(father.childElementCount); // 3
console.log(childrenlist[1]); // <p id="child2">
console.log(father.firstElementChild); // <p id="child1">
console.log(father.lastElementChild); // <p id="child3">
console.log(child1.nextElementSibling); // <p id="child2">
console.log(child1.previousElementSibling); // null
console.log(child3.nextElementSibling); // null
console.log(child3.previousElementSibling); // <p id="child2">