1. 程式人生 > >JavaScript DOM 總結(一)

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">