DOM(document object moudle),文件物件模型。它是一個中立於語言的應用程式介面(API),允許程式訪問並修改文檔的結構,內容和樣式。也就是一切語言(js,php 等)對web的操作是建立在DOM的基礎之上的。行為的發生,首先必須擷取文檔中的一個對象作為其載體。 DOM發展史 在漫長的互連網發展史上DOM一共經曆了四個階段。當前,我們正處在DOM 3階段。 DOM 0 :不是W3C規範,只是Netscape Navigator 3.0 和 IE 3.0 中的等價功能性的定義。 DOM 1:專註於HTML和XML文檔模型,提供了文檔導航和處理功能。 DOM 2:在DOM 1的基礎上提供了樣式物件模型和事件模型。 DOM 3:在DOM 2的基礎上規定了內容模型和文檔驗證,同時規定了文檔載入和儲存、文檔查看、文檔格式化和關鍵事件。 DOM關係圖 HTML文檔結構.jpg DOM眼中,html文檔就是一個樹形結構。也就是我們資料結構中的樹。很顯然document就是這個樹的根節點。<html>下面有兩個子(children)節點<head>,<body>。<head>,<body> 互為兄弟(sibling)。<table>,<span>,<p>是<body>的子節點, 是<html>的孫節點或後代(descendant)節點。 DOM節點對象 HTML文檔中各節點都是一個不同類型的節點(node)對象,每個節點都有自己的屬性和方法。利用這些屬性和方法我們就可以開始操作DOM了,包括遍曆 整個文檔樹,擷取含有某個屬性的元素等等。當然DOM中有很多類型的節點,它是怎麼樣來區分它們的了?答案是nodeType。下面我們看看具體都有哪些 類型的節點 介面 nodeType值 備忘element 1 元素節點text 3 文本節點attr 2 節點屬性comment 8 注釋節點document 9 documentdocumentFragment 11 文檔片段 在這些節點類型中,我們用的最多的就是元素(element)節點和文本(text)節點。Javascript操作HTML文檔的時候,document即指向整個文檔,<body>、<table>等節點類型即為Element。至於這個nodeType,我們可以用它來檢測節點類型。 前面我們已經提到不同的節點提供了不同的屬性和方法,現在具體每一個節點類型來看一下。document節點提供了一些常用的Factory 方法,主要用於建立可以插入文檔中各種類型的節點,詳見下表: 方法 描述createElement 建立元素節點createTextNode 建立文本節點createAttribute 建立屬性節點getElementById 擷取文檔中指定id的元素節點getElementsByTagName 擷取文檔中指定標籤的元素節點getElementByName 擷取文檔中指定名稱的元素節點 元素節點提供了一個tagName屬性用來擷取元素的標籤名稱(全為大寫),提供的一些方法主要用來插入和刪改,查詢和設定元素。詳見下表: getAttribute 以字串的形式返回指定屬性的值getAttributeNode 以Attr節點的形式返回指定屬性hasAttribute 判斷節點是否有指定名字屬性removeAttribute 刪除指定名字屬性setAttribute 設定指定名字的屬性,若沒有,添加一個 setAttributeNode 設定指定名字的屬性節點 Attr對象代表文件項目的屬性,有name、value等屬性,可以通過Node介面的attributes屬性或者調用Element介面的 getAttributeNode()方法來擷取。不過,在大多數情況下,使用Element元素屬性的最簡單方法是getAttribute()和 setAttribute()兩個方法,而不是Attr對象。 這些節點類型都是一個節點對象,而節點對象又定義了一些共有的屬性和方法,以方便的操作DOM文檔。用parentNode和 childrenNodes[]在文檔中上下移動,用nextSibling在文檔中左右移動。firstChild和lastChild可以枚舉指定節 點的子節點,通過遍曆childNodes[](這裡的childNodes[]是一個nodeList對象)數組迴圈操作這些子節點,然後通過遞迴,可 以沒舉出文檔樹中所有節點。而調用 appendChild(),insertBefore(),removeChild(),replaceChild()方法可以改變一個節點的子節點從 而改變文檔樹。下面是一些Node對象的常用屬性和方法。 Node對象的常用屬性: attributes 若該節點是一個element,返回該元素的屬性childNodes 返回當前元素的子節點,若沒有,則為nullfirstChild 返回當前節點的第一個子節點。若沒有,則為nulllastChild 返回當前節點的最後一個子節點。若沒有,則為nullnextSibling 返回當前節點的下一個兄弟節點nodeName 返回當前節點的名字,element為標記名稱parentNode 當前節點的父節點previousSibling 返回當前節點的上一個兄弟節點 Node對象常用方法: appendChild() 把一個節點增加到當前節點的childNodes[],cloneNode() 複製當前節點,若參數為true,複製當前節點及它的所有子孫節點hasChildNodes() 判斷當前節點是否擁有子節點insertBefore() 在指定節點和當前節點之間插入一個新的節點removeChild() 從文檔中刪除並返回指定子節點replaceChild() 從文檔中刪除並返回指定子節點,用另一個節點替換它 上面列舉出來的常用節點對象的屬性和方法是我們操作DOM最有用的工具,接下來,就讓我們使用上述的屬性和方法來操作日常中所見的DOM行為。 DOM操作A : 建立一段DOM片段(片段),形如: <div id=”example”> <p class=”slogan”>淘!你喜歡</p> </div> 複製代碼 1 var fragment=document.createDocumentFragment();//建立文檔片段 2 var oDiv=document.createElement("div");//建立div元素節點 3 oDiv.setAttribute("id","example");//給div節點添加id 屬性 4 var oP=document.createElement("p");//建立p元素節點 5 oP.setAttribute("class","slogan");//給p節點添加class屬性 6 var oText=document.createTextNode("淘!你喜歡")//建立文本節點 7 oP.appendChild(oText);//給p元素節點添加文本節點 8 oDiv.appendChild(op); 9 fragment.appendChild(oDiv)10 document.body.appendChild(fragment);複製代碼 這裡首先建立好片段中的元素節點,然後建立對應元素節點的屬性和文本節點。最後由內之外的為對應元素添加子節點,逐步遞推構成一個完整的DOM片段,最後將這一個片段添加到body體中。這樣你所需的DOM片段就構建好了。至於這裡用到了createDocumentFragment(),在後文中會詳述它在效能最佳化中的作用。通過這個例子我們可以學會createElement(),setAttribute(),createTextNode(),appendChild()方法。 B :遍曆文檔節點 這個例子使用了childNodes[]和遞迴方式來遍曆整個文檔,統計文檔中出現的Element元素總數,並把Element標記名全部列印出來。需要特別注意的是,在使用DOM時,必須等文檔被裝載完畢再執行遍曆等行為操作文檔。 複製代碼 1 var elementName="";//全域變數儲存元素標籤名稱 2 function countTotalElement(node){ 3 var total=0; 4 if(node.nodeType==1){//檢測是否是元素節點 5 total++//計數器加1 6 elementName=elementName+node.tagName+"\n";//儲存標籤名 7 } 8 var oChild=node.childNodes;//擷取元素節點的子節點數組 9 for(var i=0,l=oChild.length;i<l;i++){10 total+=countTotalElement(oChild[i])//遞迴每個子節點11 }12 return total;13 }