節點型別
DOM定義了Node的介面以及許多種節點型別來表示節點的多個方面!
- Document——最頂層的節點,所有的其他節點都是附屬於它的。
- DocumentType——DTD引用(使用<!DOCTYPE >語法)的物件表現形式,例如<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >。它不能包含子節點。
- DocumentFragment——可以像Document一樣來儲存其他節點。
- Element——表示起始標籤和結束標籤之間的內容,例如<tag ></tag >或者<tag / >。這是唯一可以同時包含特性和子節點的節點型別。
- Attr——代表一對特性名和特性值。這個節點型別不能包含子節點。
- Text——代表XML文件中的在起始標籤和結束標籤之間,或者CData Section內包含的普通文字。這個節點型別不能包含子節點。
- CDataSection——<![CDATA[ ]]>的物件表現形式。這個節點型別僅能包含文字節點Text作為子節點。
- Entity——表示在DTD中的一個實體定義,例如<!ENTITY foo "foo">。這個節點型別不能包含子節點。
- EntityReference——代表一個實體引用,例如"。這個節點型別不能包含子節點。
- ProcessingInstruction——代表一個PI(處理指令)。這個節點型別不能包含子節點。
- Comment——代表註釋。這個節點型別不能包含子節點。
- Notation——代表在DTD中定義的記號。這個很少用到,所以我們不會討論。
還定義了對應不同節點型別的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)
節點型別常量都是Node物件的屬性,但是IE不支援Node物件,但是仍可以使用數值
Node介面也定義了一些所有節點型別都包含的特性和方法。我們在下面的表格中列出了這些特性和方法:
特性/方法 | 型別/返回型別 | 說 明 |
nodeName | String | 節點的名字;根據節點的型別而定義,元素節點返回tagName,文字節點返回#text,屬性節點返回屬性名 |
nodeValue | String | 節點的值;根據節點的型別而定義.元素節點此屬性為空,文字節點些屬性即為節點中的字串,屬性節點返回屬性值 |
nodeType | Number | 節點的型別常量值之一 |
ownerDocument | Document | 指向這個節點所屬的文件 |
firstChild | Node | 指向在childNodes列表中的第一個節點 |
lastChild | Node | 指向在childNodes列表中的最後一個節點 |
childNodes | NodeList | 所有子節點的列表 |
previousSibling | Node | 指向前一個兄弟節點;如果這個節點就是第一個兄弟節點,那麼該值為null |
nextSibling | Node | 指向後一個兄弟節點;如果這個節點就是最後一個兄弟節點,那麼該值為null |
hasChildNodes() | Boolean | 當childNodes包含一個或多個節點時,返回真 |
attributes | NamedNodeMap | 包含了代表一個元素的特性的Attr物件;僅用於Element節點 |
appendChild(node) | Node | 將node新增到childNodes的末尾 |
removeChild(node) | Node | 從childNodes中刪除node |
replaceChild (newnode,oldnode) | Node | 將childNodes中的oldnode替換成newnode |
insertBefore (newnode,refnode) | Node | 在childNodes中的refnode之前插入newnode |
除節點外,DOM還定義了一些助手物件,它們可以和節點一起使用,但不是DOM文件必有的部分。
- NodeList——節點陣列,按照數值進行索引;用來表示一個元素的子節點。比如childNodes。NodeList有個length屬性表示節點數量
- NamedNodeMap——同時用數值和名字進行索引的節點表;用於表示元素特性。比如元素的attributes。NamedNodeMap物件也有一個length屬性來指示它所包含的節點的數量。
這些助手物件為處理DOM文件提供附加的訪問和遍歷方法。
屬性節點
正如前面提到的,即便Node介面已具有attributes方法,且已被所有型別的節點繼承,然而,只有Element節點才能有特性。Element節點的attributes屬性其實是NamedNodeMap,它提供一些用於訪問和處理其內容的方法:
- getNamedItem(name)——返回nodeName屬性值等於name的節點;
- removeNamedItem(name)——刪除nodeName屬性值等於name的節點;
- setNamedItem(node)——將node新增到列表中,按其nodeName屬性進行索引;
- item(pos)——像NodeList一樣,返回在位置pos的節點;
請記住這些方法都是返回一個Attr節點,而非特性值。
當NamedNodeMap用於表示特性時,其中每個節點都是Attr節點,它的nodeName屬性被設定為特性名稱,而nodeValue屬性被設定為特性的值。示例:
<p id="p1" style="background-color:red;" title="P!!!">Some Text!</p> var p1 = document.getElementById("p1"); //訪問ID屬性 alert(p1.attributes.getNamedItem("id")).nodeValue; //也可以用數值來訪問ID屬性 alert(p1.attributes.item(0)).nodeValue; //也可以改變它的值 p1.attributes.getNamedItem("id").nodeValue = "newP1";
Attr節點也有一個完全等同於(同時也完全同步於)nodeValue屬性的value屬性,並且有name屬性和nodeName屬性保持同步。我們可以隨意使用這些屬性來修改或變更特性。但這些方法都比較複雜,所以DOM又定義了三個元素方法來幫助訪問特性:
- getAttribute(name)——等於attributes.getNamedItem(name).value
- setAttribute(name, newValue)——等於attribute.getNamedItem(name).value = newValue
- removeAttribute(name)——等於attributes.removeNamedItem(name)
NodeList
事實上我們早接觸過NodeList了
var allTags = document.getElementsByTagName("*"); alert(allTags.item(1).tagName);//訪問了第二個元素 alert(allTags[0]);//在JavaScript可以這樣訪問第一個元素,但這隻能是JavaScript里正常執行
getElementsByTagName與getElementsByName都返回NodeList,可以使用item(index)方法訪問其中的內容,在JavaScript中還可使用陣列形式的下標訪問!
建立和操縱節點
迄今為止,已經學過了如何訪問文件中的不同節點,不過這僅僅是使用DOM所能實現的功能中的很小一部分。還能新增、刪除、替換(或者其他操作)DOM文件中的節點。正是這些功能使得DOM具有真正意義上的動態性。
建立新節點
DOM Document(文件)中有一些方法用於建立不同型別的節點,即便在所有的瀏覽器中的瀏覽器document物件並不需要全部支援所有的方法。下面的表格列出了包含在DOM Level 1中的方法,並列出不同的瀏覽器是否支援項。
方 法 | 描 述 | IE | MOZ | OP | SAF |
createAttribute (name) | 用給定名稱name建立特性節點 | × | × | × | - |
createCDATASection (text) | 用包含文字text的文字子節點建立一個CDATA Section | - | × | - | - |
createComment(text) | 建立包含文字text的註釋節點 | × | × | × | × |
createDocumentFragment() | 建立文件碎片節點 | × | × | × | × |
createElement (tagname) | 建立標籤名為tagname的元素 | × | × | × | × |
createEntity Reference(name) | 建立給定名稱的實體引用節點 | - | × | - | - |
createProcessing Instruction(target, data) | 建立包含給定target和data的PI節點 | - | × | - | - |
createTextNode(text) | 建立包含文字text的文字節點 | × | × | × | × |
注:IE = Windows的IE 6;MOZ = 任意平臺的Mozilla 1.5;OP=任意平臺的Opera 7.5;SAF=MacOS的Safari 1.2
最常用到的幾個方法是:createDocumentFragment()、createElement()和createText- Node();其他的一些方法要麼就是沒什麼用(createComment()),要麼就是瀏覽器的支援不夠,目前還不太能用。
動態建立一個段落示例
var p = document.createElement("p");//建立一個元素節點,傳入標籤名 var txt = document.createTextNode("建立文字節點,傳引數即是文字內容"); p.appendChild(txt);//將txt所引用的文字節點插入p到p的最後面(在這裡p是空的) //直到現在,頁面不會出現任何內容,必須將建立的節點插入到文件中 document.body.appendChild(p);//p將出現在最後
移動,刪除節點方法及注意事項——appendChild,removeChild,replaceChild,insertBefore
var p1 = document.getElementById("p1"); document.body.appendChild(p1);//p1將會被作為body的最後一個子節點,然而頁面上仍只有一個p p1.parentNode.removeChild(p1);//removeChild必須是要刪除的節點的父節點呼叫 //p1將會從頁面上消失,然而它並沒有完全消失,我們還可以再將其插入文件 document.body.appendChild(p1);//因為變數p1包含了節點的引用 var p2 = document.getElementById("p2"); p2.parentNode.replaceChild(p1,p2);//p2將會被替換成p1,p2將消失 //而p1將從原來的位置移到p2的位置
克隆節點——cloneNode
基於上面的原因,DOM為我們提供了一個克隆節點的方法用於生成一個節點的副本
var p1 = document.getElementById("p1"); var p2 = p1.cloneNode(); document.body.appendChild(p2);//頁面上將會多出一個段落,不過段落中什麼都沒有 p2 = p1.cloneNode(true);//使用引數true表示克隆節點時包含子節點 document.body.appendChild(p2);