節(jié)點的屬性
使用 DOM 節(jié)點時需要一些屬性和方法,因此我們首先來討論節(jié)點的屬性和方法。DOM 節(jié)點的屬性主要有:
- nodeName報告節(jié)點的名稱(詳見下述)。
- nodeValue提供節(jié)點的 “值”(詳見后述)。
- parentNode返回節(jié)點的父節(jié)點。記住,每個元素、屬性和文本都有一個父節(jié)點。
- childNodes是節(jié)點的孩子節(jié)點列表。對于 HTML,該列表僅對元素有意義,文本節(jié)點和屬性節(jié)點都沒有孩子。
- firstChild僅僅是childNodes列表中第一個節(jié)點的快捷方式。
- lastChild是另一種快捷方式,表示childNodes列表中的最后一個節(jié)點。
- previousSibling返回當前節(jié)點之前的節(jié)點。換句話說,它返回當前節(jié)點的父節(jié)點的childNodes列表中位于該節(jié)點前面的那個節(jié)點(如果感到迷惑,重新讀前面一句)。
- nextSibling類似于previousSibling屬性,返回父節(jié)點的childNodes列表中的下一個節(jié)點。
- attributes僅用于元素節(jié)點,返回元素的屬性列表。
其他少數(shù)幾種屬性實際上僅用于更一般的 XML 文檔,在處理基于 HTML 的網(wǎng)頁時沒有多少用處。
不常用的屬性
上述大部分屬性的意義都很明確,除了nodeName和nodeValue屬性以外。我們不是簡單地解釋這兩個屬性,而是提出兩個奇怪的問題:文本節(jié)點的nodeName應(yīng)該是什么?類似地,元素的nodeValue應(yīng)該是什么?
如果這些問題難住了您,那么您就已經(jīng)了解了這些屬性固有的含糊性。nodeName和nodeValue實際上并非適用于所有節(jié)點類型(節(jié)點的其他少數(shù)幾個屬性也是如此)。這就說明了一個重要概念:任何這些屬性都可能返回空值(有時候在 JavaScript 中稱為 “未定義”)。比方說,文本節(jié)點的nodeName屬性是空值(或者在一些瀏覽器中稱為 “未定義”),因為文本節(jié)點沒有名稱。如您所料,nodeValue返回節(jié)點的文本。
類似地,元素有nodeName,即元素名,但元素的nodeValue屬性值總是空。屬性同時具有nodeName和nodeValue。下一節(jié)我還將討論這些單獨的類型,但是因為這些屬性是每個節(jié)點的一部分,因此在這里有必要提一提。
節(jié)點方法
接下來看看所有節(jié)點都具有的方法(與節(jié)點屬性一樣,我省略了實際上不適用于多數(shù) HTML DOM 操作的少數(shù)方法):
- insertBefore(newChild, referenceNode)將newChild節(jié)點插入到referenceNode之前。記住,應(yīng)該對newChild的目標父節(jié)點調(diào)用該方法。
- replaceChild(newChild, oldChild)用newChild節(jié)點替換oldChild節(jié)點。
- removeChild(oldChild)從運行該方法的節(jié)點中刪除oldChild節(jié)點。
- appendChild(newChild)將newChild添加到運行該函數(shù)的節(jié)點之中。newChild被添加到目標節(jié)點孩子列表中的末端。
- hasChildNodes()在調(diào)用該方法的節(jié)點有孩子時則返回 true,否則返回 false。
- hasAttributes()在調(diào)用該方法的節(jié)點有屬性時則返回 true,否則返回 false。
注意,大部分情況下所有這些方法處理的都是節(jié)點的孩子。這是它們的主要用途。如果僅僅想獲取文本節(jié)點值或者元素名,則不需要調(diào)用這些方法,使用節(jié)點屬性就可以了。
通用節(jié)點類型
現(xiàn)在已經(jīng)介紹了 DOM 節(jié)點的一些特性和屬性(以及一些奇特的地方),下面開始講述您將用到的一些特殊節(jié)點類型。多數(shù) Web 應(yīng)用程序中只用到四種節(jié)點類型:
- 文檔節(jié)點表示整個 HTML 文檔。
- 元素節(jié)點表示 HTML 元素,如a或img。
- 屬性節(jié)點表示 HTML 元素的屬性,如href(a元素)或src(img元素)。
- 文本節(jié)點表示 HTML 文檔中的文本,如 “Click on the link below for a complete set list”。這是出現(xiàn)在p、a或h2這些元素中的文字。
處理 HTML 時,95% 的時間是跟這些節(jié)點類型打交道。因此本文的其余部分將詳細討論這些節(jié)點。(將來討論 XML 的時候?qū)⒔榻B其他一些節(jié)點類型。)
文檔節(jié)點
基本上所有基于 DOM 的代碼中都要用到的第一個節(jié)點類型是文檔節(jié)點。文檔節(jié)點實際上并不是 HTML(或 XML)頁面中的一個元素而是頁面本身。因此在 HTML Web 頁面中,文檔節(jié)點就是整個 DOM 樹。在 JavaScript 中,可以使用關(guān)鍵字document訪問文檔節(jié)點:
// These first two lines get the DOM tree for the current Web page,
// and then the <html> element for that DOM tree
var myDocument = document;
var htmlElement = myDocument.documentElement;
|
JavaScript 中的document關(guān)鍵字返回當前網(wǎng)頁的 DOM 樹。從這里可以開始處理樹中的所有節(jié)點。
也可使用document對象創(chuàng)建新節(jié)點,如下所示:
- createElement(elementName)使用給定的名稱創(chuàng)建一個元素。
- createTextNode(text)使用提供的文本創(chuàng)建一個新的文本節(jié)點。
- createAttribute(attributeName)用提供的名稱創(chuàng)建一個新屬性。
這里的關(guān)鍵在于這些方法創(chuàng)建節(jié)點,但是并沒有將其附加或者插入到特定的文檔中。因此,必須使用前面所述的方法如insertBefore()或appendChild()來完成這一步。因此,可使用下面的代碼創(chuàng)建新元素并將其添加到文檔中:
var pElement = myDocument.createElement("p");
var text = myDocument.createTextNode("Here's some text in a p element.");
pElement.appendChild(text);
bodyElement.appendChild(pElement);
|
一旦使用document元素獲得對 Web 頁面 DOM 樹的訪問,就可以直接使用元素、屬性和文本了。
元素節(jié)點
雖然會大量使用元素節(jié)點,但很多需要對元素執(zhí)行的操作都是所有節(jié)點共有的方法和屬性,而不是元素特有的方法和屬性。元素只有兩組專有的方法:
- 與屬性處理有關(guān)的方法:
- getAttribute(name)返回名為name的屬性值。
- removeAttribute(name)刪除名為name的屬性。
- setAttribute(name, value)創(chuàng)建一個名為name的屬性并將其值設(shè)為value。
- getAttributeNode(name)返回名為name的屬性節(jié)點(屬性節(jié)點在 下一節(jié) 介紹)。
- removeAttributeNode(node)刪除與指定節(jié)點匹配的屬性節(jié)點。
- 與查找嵌套元素有關(guān)的方法:
- getElementsByTagName(elementName)返回具有指定名稱的元素節(jié)點列表。
這些方法意義都很清楚,但還是來看幾個例子吧。
處理屬性
處理元素很簡單,比如可用document對象和上述方法創(chuàng)建一個新的img元素:
var imgElement = document.createElement("img");
imgElement.setAttribute("src", "http://www.headfirstlabs.com/Images/hraj_cover-150.jpg");
imgElement.setAttribute("width", "130");
imgElement.setAttribute("height", "150");
bodyElement.appendChild(imgElement);
|
現(xiàn)在看起來應(yīng)該非常簡單了。實際上,只要理解了節(jié)點的概念并知道有哪些方法可用,就會發(fā)現(xiàn)在 Web 頁面和 JavaScript 代碼中處理 DOM 非常簡單。在上述代碼中,JavaScript 創(chuàng)建了一個新的img元素,設(shè)置了一些屬性然后添加到 HTML 頁面的 body 元素中。
查找嵌套元素
發(fā)現(xiàn)嵌套的元素很容易。比如,下面的代碼用于發(fā)現(xiàn)和刪除 清單 3 所示 HTML 頁面中的所有img元素:
// Remove all the top-level <img> elements in the body
if (bodyElement.hasChildNodes()) {
for (i=0; i<bodyElement.childNodes.length; i++) {
var currentNode = bodyElement.childNodes[i];
if (currentNode.nodeName.toLowerCase() == "img") {
bodyElement.removeChild(currentNode);
}
}
}
|
也可以使用getElementsByTagName()完成類似的功能:
// Remove all the top-level <img> elements in the body
var imgElements = bodyElement.getElementsByTagName("img");
for (i=0; i<imgElements.length; i++) {
var imgElement = imgElements.item[i];
bodyElement.removeChild(imgElement);
}
|
屬性節(jié)點
DOM 將屬性表示成節(jié)點,可以通過元素的attributes來訪問元素的屬性,如下所示:
// Remove all the top-level <img> elements in the body
var imgElements = bodyElement.getElementsByTagName("img");
for (i=0; i<imgElements.length; i++) {
var imgElement = imgElements.item[i];
// Print out some information about this element
var msg = "Found an img element!";
var atts = imgElement.attributes;
for (j=0; j<atts.length; j++) {
var att = atts.item(j);
msg = msg + ""n " + att.nodeName + ": '" + att.nodeValue + "'";
}
alert(msg);
bodyElement.removeChild(imgElement);
}
|
屬性的奇特之處
對于 DOM 來說屬性有一些特殊的地方。一方面,屬性實際上并不像其他元素或文本那樣是元素的孩子,換句話說,屬性并不出現(xiàn)在元素 “之下”。同時,屬性顯然和元素有一定的關(guān)系,元素 “擁有” 屬性。DOM 使用節(jié)點表示屬性,并允許通過元素的專門列表來訪問屬性。因此屬性是 DOM 樹的一部分,但通常不出現(xiàn)在樹中。有理由說,屬性和 DOM 樹結(jié)構(gòu)其他部分之間的關(guān)系有點模糊。
|
|
需要指出的是,attributes屬性實際上是對節(jié)點類型而非局限于元素類型來說的。有點古怪,不影響您編寫代碼,但是仍然有必要知道這一點。
雖然也能使用屬性節(jié)點,但通常使用元素類的方法處理屬性更簡單。其中包括:
- getAttribute(name)返回名為name的屬性值。
- removeAttribute(name)刪除名為name的屬性。
- setAttribute(name, value)創(chuàng)建一個名為name的屬性并將其值設(shè)為value。
這三個方法不需要直接處理屬性節(jié)點。但允許使用簡單的字符串屬性設(shè)置和刪除屬性及其值。
文本節(jié)點
需要考慮的最后一種節(jié)點是文本節(jié)點(至少在處理 HTML DOM 樹的時候如此)。基本上通常用于處理文本節(jié)點的所有屬性都屬于節(jié)點對象。實際上,一般使用nodeValue屬性來訪問文本節(jié)點的文本,如下所示:
var pElements = bodyElement.getElementsByTagName("p");
for (i=0; i<pElements.length; i++) {
var pElement = pElements.item(i);
var text = pElement.firstChild.nodeValue;
alert(text);
}
|
少數(shù)其他幾種方法是專門用于文本節(jié)點的。這些方法用于增加或分解節(jié)點中的數(shù)據(jù):
- appendData(text)將提供的文本追加到文本節(jié)點的已有內(nèi)容之后。
- insertData(position, text)允許在文本節(jié)點的中間插入數(shù)據(jù)。在指定的位置插入提供的文本。
- replaceData(position, length, text)從指定位置開始刪除指定長度的字符,用提供的文本代替刪除的文本。
什么節(jié)點類型?
到目前為止看到的多數(shù)代碼都假設(shè)已經(jīng)知道處理的節(jié)點是什么類型,但情況并非總是如此。比方說,如果在 DOM 樹中導航并處理一般的節(jié)點類型,可能就不知道您遇到了元素還是文本。也許獲得了p元素的所有孩子,但是不能確定處理的是文本、b元素還是img元素。這種情況下,在進一步的處理之前需要確定是什么類型的節(jié)點。
所幸的是很容易就能做到。DOM 節(jié)點類型定義了一些常量,比如:
- Node.ELEMENT_NODE是表示元素節(jié)點類型的常量。
- Node.ATTRIBUTE_NODE是表示屬性節(jié)點類型的常量。
- Node.TEXT_NODE是表示文本節(jié)點類型的常量。
- Node.DOCUMENT_NODE是表示文檔節(jié)點類型的常量。
還有其他一些節(jié)點類型,但是對于 HTML 除了這四種以外很少用到。我有意沒有給出這些常量的值,雖然 DOM 規(guī)范中定義了這些值,永遠不要直接使用那些值,因為這正是常量的目的!
nodeType 屬性
可使用nodeType屬性比較節(jié)點和上述常量 —— 該屬性定義在 DOM node 類型上因此可用于所有節(jié)點,如下所示:
var someNode = document.documentElement.firstChild;
if (someNode.nodeType == Node.ELEMENT_NODE) {
alert("We've found an element node named " + someNode.nodeName);
} else if (someNode.nodeType == Node.TEXT_NODE) {
alert("It's a text node; the text is " + someNode.nodeValue);
} else if (someNode.nodeType == Node.ATTRIBUTE_NODE) {
alert("It's an attribute named " + someNode.nodeName
+ " with a value of '" + someNode.nodeValue + "'");
}
|
這個例子非常簡單,但說明了一個大問題:得到節(jié)點的類型非常簡單。更有挑戰(zhàn)性的是知道節(jié)點的類型之后確定能做什么,只要掌握了節(jié)點、文本、屬性和元素類型提供了什么屬性和方法,就可以自己進行 DOM 編程了。
實踐中的挫折
nodeType屬性似乎是使用節(jié)點的一個入場卷 —— 允許確定要處理的節(jié)點類型然后編寫處理該節(jié)點的代碼。問題在于上述Node常量定義不能正確地用于 Internet Explorer。因此如果在代碼中使用Node.ELEMENT_NODE、Node.TEXT_NODE或其他任何常量,Internet Explorer 都將返回如 圖 4 所示的錯誤。
圖 4. Internet Explorer 報告錯誤

任何時候在 JavaScript 中使用Node常量,Internet Explorer 都會報錯。因為多數(shù)人仍然在使用 Internet Explorer,應(yīng)該避免在代碼中使用Node.ELEMENT_NODE或Node.TEXT_NODE這樣的構(gòu)造。盡管據(jù)說即將發(fā)布的新版本 Internet Explorer 7.0 將解決這個問題,但是在 Internet Explorer 6.x 退出舞臺之前仍然要很多年。因此應(yīng)避免使用Node,要想讓您的 DOM 代碼(和 Ajax 應(yīng)用程序)能用于所有主要瀏覽器,這一點很重要。
摘自:http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro5/?S_TACT=105AGX52&S_CMP=techcsdn。
posted on 2008-03-11 11:32
Tiger1102 閱讀(1854)
評論(0) 編輯 收藏 所屬分類:
每日進階