DOM總結1:DOM基礎

0. DOM簡介


任何一種技術都是有它存在的意義,DOM正是爲了方便操作HTML文檔而誕生的技術。在沒有DOM的時代,爲了操作HTML元素曾發展出了DHTML(動態HTML),後來由於微軟和Netscape的瀏覽器大戰而銷聲匿跡。DOM脫胎於DHTML,並於1998年DOM 1級成爲了W3C的推薦標準。現在利用JavaScript操作DOM已經成爲基礎前端技術,被各大瀏覽器完善支持。


DOM(Document Object Model,文檔對象模型),是一種針對HTML和XML文檔編程API。DOM將整個HTML或XML文檔映射爲一個層次化的節點樹,用以節點的增刪改查操作,以達到改變頁面的目的。每個HTML或XML元素都可以看成一個節點,每個節點都有對應的數據和層次結構,使用JavaScript等腳本語言可以對節點的進行操作。

例如如下HTML文檔:

<html>
    <head>
        <title>learnDOM</title>
    </head>
    <body>
        <p>hello</p>
        <h1>world</h1>
    </body>
</html>

可將此HTML文檔表示爲節點的層次結構:


其實html上冊還有一個根節點:文檔節點。html節點稱爲文檔元素,任何一個HTML文檔只有一個文檔元素,因此html節點能表示整個文檔。整個DOM樹是一種典型的樹狀數據結構,例如body節點擁有兩個子節點p和h1,文本節點"learnDOM"父節點爲title。


1. 節點類型


DOM 1級定義了一個Node接口,該接口由DOM中所有節點類型來實現。相應的,在JavaScript中由Node類型實現了這個接口,JavaScript的其他所有節點類型都繼承自Node類型,因此所有節點類型共享基本屬性和方法。

每個節點都有一個nodeType屬性來表明節點類型。Node類型定義了12個類型,由數值常量1~12來表示。常用節點類型有:

節點類型 數值常量 字符常量
Element(元素節點) 1 ELEMENT_NODE
Attr(屬性節點) 2 ATTRIBUTE_NODE
Text(文本節點) 3 TEXT_NODE
Comment(註釋節點) 8 COMMENT_NODE
Document(文檔節點) 9 DOCUMENT_NODE
DocumentType(文檔類型節點) 10 DOCUMENT_TYPE_NODE
DocumentFragment(文檔片段節點) 11 DOCUMENT_FRAGMENT_NODE
除IE外各大瀏覽器都支持使用字符常量。下面簡要列舉各節點類型的含義:
1)Element(元素節點),是組成節點樹的重要部分,通常擁有子元素、文本節點等子節點,也是唯一能擁有屬性的節點類型,例如:
<html>, <head>, <meta>, <div>等

都是元素節點。


2)Attr(屬性節點),是元素節點的一部分,不能單獨作爲節點出現在節點樹中。例如:

<div id="addr"></div>

中id就是元素節點div的屬性節點。


3)Text(文本節點),只包含文本內容的節點,在XML中也稱爲字符數據,可爲空字符。節點樹中,元素的文本內容和屬性的文本內容都是由文本節點來表示的。例如:

<title>learnDOM</title>

中"learnDOM"就是文本節點。


4)Comment(註釋節點),表示文檔中註釋的內容。


5)Document(文檔節點),是文檔的根節點。在HTML文檔的節點樹中處於html節點之上的節點爲文檔節點。


6)DocumentType(文檔類型節點),每個文檔都有一個類型屬性,值或爲空,或爲DocumentType對象。在HTML中:

<!DOCTYPE html>

就是文檔類型節點。


7)DocumentFragment(文檔片段節點),是文檔的片段,並不屬於文檔節點樹。例如:

var frag = document.createDocumentFragment();

frag就爲一個文檔片段,可對其操作後寫入文檔樹,文檔片段就起了類似臨時變量的作用。


接下來舉一個判斷節點類型的例子:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>learnDOM</title>
    </head>
    <body>
        <div id="addr">元素節點</div>
        <script>
            var divNode = document.getElementById("addr");
            if (divNode.nodeType === Node.ELEMENT_NODE) {
                console.log("A element node");
            }
        </script>
    </body>
</html>
將div節點的id"addr"傳入getElementById()方法,得到一個節點元素divNode。判斷divNode的類型可通過上述if語句。注意IE中只支持與數值常量,ELEMENT_NODE這種字符常量是無法識別的。

上例中通過節點元素的nodeType屬性判斷節點類型,除此之外常用屬性還有nodeNamenodeValue。例如:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>learnDOM</title>
    </head>
    <body>
        <!-- learnNodeType -->
        <div id="addr">元素節點</div>
        <script>
            //元素節點
            var divNode = document.getElementById("addr");
            console.log(divNode.nodeName);   //div
            console.log(divNode.nodeValue);  //null

            //屬性節點
            var attrNode = divNode.attributes[0];
            console.log(attrNode.nodeName);  //id
            console.log(attrNode.nodeValue); //addr

            //文本節點
            var textNode = divNode.childNodes[0];
            console.log(textNode.nodeName); //#text
            console.log(textNode.nodeValue);//元素節點

            //註釋節點
            var commentNode = document.body.childNodes[1];//註釋前空白爲[0]
            console.log(commentNode.nodeName);//#comment
            console.log(commentNode.nodeValue);//learnNodeType

            //文檔類型節點
            console.log(document.doctype.nodeName); //html
            console.log(document.doctype.nodeValue);//null
            
            //文檔片段節點
            var frag = document.createDocumentFragment();//創建文檔片段
            console.log(frag.nodeName);  //#document-fragment
            console.log(frag.nodeValue); //null
        </script>
    </body>
</html>

2.  DOM方法和屬性


HTML文檔被瀏覽器解析爲一棵DOM樹,要想操作HTML文檔就要通過JavaScript來操作DOM節點。對DOM的操作可以總結爲“增刪改查”,即:增加DOM節點,刪除DOM節點,更新DOM節點和查詢遍歷DOM節點。

DOM是一種對象,有其相應的方法和屬性。通過DOM方法可以執行DOM操作,如增改節點元素;通過屬性可以獲取或設置節點。

通過各種DOM方法我們可以對HTML節點元素進行增刪改查操作。常用方法有:
  • getElementById(),返回指定ID的元素
  • getElementsByTagName(),返回指定標籤名稱的所有元素節點集合
  • getElementsByClassName(),返回指定類名的所有元素節點集合
  • appendChild(),添加新節點到指定節點
  • removeChild(),刪除子節點
  • replaceChild(),替換子節點
  • insertBefore(),在指定節點前插入新節點
  • createAttribute(),創建屬性節點
  • createElement(),創建元素節點
  • createTextNode(),創建文本節點
  • getAttribute(),返回指定屬性值
  • setAttribute(),修改指定屬性值

常用的屬性有:
  • innerHTML,節點文本值
  • parentNode,節點的父節點
  • childNodes,節點的子節點
  • attributes,節點的屬性節點

下面在通過實例說明DOM方法和屬性的常見用法:

2.1 DOM獲取

若要操作DOM節點首先要獲取到DOM節點。常見方法如document.getElementById()document.getElementsByTagName(),以及CSS選擇器document.getElementsByClassName()。getElementById()與後兩者區別在於:ID可以定位到HTML中唯的DOM節點,後兩種方法會得到一組DOM節點。我們可以通過先定位父節點後向下選擇的方法精確定位DOM。例如:
    <h1 id="country">countries</h1>
    <div id="div_list">
        <p class="AS">CN</p>
        <p class="NA">US</p>
        <p class="EU">UK</p>
        <p class="EU">FR</p>
        <p class="AS">JP</p>
        <p class="AS">KR</p>
    </div>

    <script>
        //獲取ID爲"country"的節點
        var countries = document.getElementById("country");

        //先定位ID爲"div_list"的節點,後獲取其內部所有p節點
        var ps = document.getElementById("div_list").getElementsByTagName("p");

        //先定位ID爲"div_list"的節點,後獲取其內部所有class爲EU的節點
        var eus = document.getElementById("div_list").getElementsByClassName("EU");

        //獲取div_list所有子節點,第一個子節點,最後一個子節點
        var divTest = document.getElementById("div_list");
        var divTestChilds = divTest.childNodes;
        var firstChild = divTest.firstChild;
        var lastChild = divTest.lastChild;
    </script>
或者用querySelector()querySelectorAll(),注意IE8+版本纔有支持。具體用法見https://developer.mozilla.org/zh-CN/docs/Web/API/Document/

2.2 DOM修改

得到某個DOM節點後可對其進行修改。
1)修改innerHTML屬性,innerHTML 屬性設置或返回表格行的開始和結束標籤之間的 HTML。可對節點文本進行修改:
        //獲取節點
        var h = document.getElementById("country");
        
        //設置文本
        h.innerHTML = "hello";

        //設置HTML
        h.innerHTML = "hello <span style=\"color:red\">red</span> ";

2)修改innerTexttextContent屬性。這兩種屬性可以對字符串進行HTML編碼,防止惡意修改。用法與innerHTML類似。

3)修改CSS。DOM節點對象的style屬性對應CSS格式設置,例如:
        var divTest = document.getElementById("div_list");

        divTest.style.color = "#00ff00";
        divTest.style.fontSize = "10px";

2.3 DOM刪除

要刪除一個節點首先要獲取它本身及其父節點,通過調用父節點的removeChild()方法進行刪除:
        //獲取待刪除節點
        var self = document.getElementById("div_list");
        
        //獲取父節點
        var parent = self.parentNode;

        //刪除
        var removed = parent.removeChild(self);

        console.log(removed === self); //true
若使用父節點的children屬性進行遍歷刪除,注意children屬性是隻讀的,並且隨着操作會實時更新:
    <div id="div_list">
        <p class="AS">CN</p>
        <p class="NA">US</p>
        <p class="EU">UK</p>
        <p class="EU">FR</p>
        <p class="AS">JP</p>
        <p class="AS">KR</p>
    </div>

    <script>
        var parent = document.getElementById("div_list");

        parent.removeChild(parent.children[0]);
        parent.removeChild(parent.children[5]);//error,節點只剩了五個,children[5]不存在
    </script>


2.4 DOM插入

1)直接修改innerHTML。
當DOM節點爲空時,直接修改其innerHTML屬性即可“插入”節點。例如:
    <div id="blank"></div>
    
    <script>
        var d = document.getElementById("blank");
        d.innerHTML = "hello";
    </script>
但是節點非空時會將原內容覆蓋。

2)appendChild()方法,將新節點插入到父節點最後。例如:
    <p id="kr">KR</p>
    <div id="div_list">
        <p class="AS">CN</p>
        <p class="NA">US</p>
        <p class="EU">UK</p>
        <p class="EU">FR</p>
        <p class="AS">JP</p>
    </div>
    <script>
        var list = document.getElementById("div_list");
        var kr = document.getElementById("kr");
        list.appendChild(kr);
    </script>
<p id="kr">KR</p>被插入到list最後,並且原位置的kr會被刪除,相當於完成了節點的移動。

我們也能從零創建一個新節點並插入父節點中:
        var list = document.getElementById("div_list");
        var newNode = document.createElement("p");
        newNode.id = "kr";
        newNode.innerHTML = "KR";
        list.appendChild(newNode);

3)insertBefore()方法,能夠靈活確定插入位置。該方法調用形式爲:
parentElement.insertBefore(newElement, referenceElement);
能將子節點newElement插入到referenceElement之前。例如:
    <p id="kr">KR</p>
    <div id="div_list">
        <p class="AS">CN</p>
        <p class="NA">US</p>
        <p class="EU">UK</p>
        <p class="EU">FR</p>
        <p class="AS">JP</p>
    </div>
    <script>
        var list = document.getElementById("div_list");
        var ref = list.children[2];
        var node = document.getElementById("kr");
        list.insertBefore(node, ref);
    </script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章