使用 DOM 节点时需要一些属性和方法,因此我们首先来讨论节点的属性和方法。DOM 节点的属性主要有:
nodeName
报告节点的名称(详见下述)。nodeValue
提供节点的 “值”(详见后述)。parentNode
返回节点的父节点。记住,每个元素、属性和文本都有一个父节点。childNodes
是节点的孩子节点列表。对于 HTML,该列表仅对元素有意义,文本节点和属性节点都没有孩子。firstChild
仅仅是childNodes
列表中第一个节点的快捷方式。lastChild
是另一种快捷方式,表示childNodes
列表中的最后一个节点。previousSibling
返回当前节点之前 的节点。换句话说,它返回当前节点的父节点的childNodes
列表中位于该节点前面的那个节点(如果感到迷惑,重新读前面一句)。nextSibling
类似于previousSibling
属性,返回父节点的childNodes
列表中的下一个节点。attributes
仅用于元素节点,返回元素的属性列表。
其他少数几种属性实际上仅用于更一般的 XML 文档,在处理基于 HTML 的网页时没有多少用处。
上述大部分属性的意义都很明确,除了 nodeName
和 nodeValue
属性以外。我们不是简单地解释这两个属性,而是提出两个奇怪的问题:文本节点的 nodeName
应该是什么?类似地,元素的 nodeValue
应该是什么?
如果这些问题难住了您,那么您就已经了解了这些属性固有的含糊性。nodeName
和 nodeValue
实际上并非适用于所有 节点类型(节点的其他少数几个属性也是如此)。这就说明了一个重要概念:任何这些属性都可能返回空值(有时候在 JavaScript 中称为 “未定义”)。比方说,文本节点的 nodeName
属性是空值(或者在一些浏览器中称为 “未定义”),因为文本节点没有名称。如您所料,nodeValue
返回节点的文本。
类似地,元素有 nodeName
,即元素名,但元素的 nodeValue
属性值总是空。属性同时具有 nodeName
和 nodeValue
。下一节我还将讨论这些单独的类型,但是因为这些属性是每个节点的一部分,因此在这里有必要提一提。
现在看看 清单 1,它用到了一些节点属性。
// 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; // What's the name of the <html> element? "html" alert("The root element of the page is " + htmlElement.nodeName); // Look for the <head> element var headElement = htmlElement.getElementsByTagName("head")[0]; if (headElement != null) { alert("We found the head element, named " + headElement.nodeName); // Print out the title of the page var titleElement = headElement.getElementsByTagName("title")[0]; if (titleElement != null) { // The text will be the first child node of the <title> element var titleText = titleElement.firstChild; // We can get the text of the text node with nodeValue alert("The page title is '" + titleText.nodeValue + "'"); } // After <head> is <body> var bodyElement = headElement.nextSibling; while (bodyElement.nodeName.toLowerCase() != "body") { bodyElement = bodyElement.nextSibling; } // We found the <body> element... // We'll do more when we know some methods on the nodes. } |
|
接下来看看所有节点都具有的方法(与节点属性一样,我省略了实际上不适用于多数 HTML DOM 操作的少数方法):
insertBefore(newChild, referenceNode)
将newChild
节点插入到referenceNode
之前。记住,应该对newChild
的目标父节点调用该方法。replaceChild(newChild, oldChild)
用newChild
节点替换oldChild
节点。removeChild(oldChild)
从运行该方法的节点中删除oldChild
节点。appendChild(newChild)
将newChild
添加到运行该函数的节点之中。newChild
被添加到目标节点孩子列表中的末端。hasChildNodes()
在调用该方法的节点有孩子时则返回 true,否则返回 false。hasAttributes()
在调用该方法的节点有属性时则返回 true,否则返回 false。
注意,大部分情况下所有这些方法处理的都是节点的孩子。这是它们的主要用途。如果仅仅想获取文本节点值或者元素名,则不需要调用这些方法,使用节点属性就可以了。清单 2 在 清单 1 的基础上增加了方法使用。
// 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; // What's the name of the <html> element? "html" alert("The root element of the page is " + htmlElement.nodeName); // Look for the <head> element var headElement = htmlElement.getElementsByTagName("head")[0]; if (headElement != null) { alert("We found the head element, named " + headElement.nodeName); // Print out the title of the page var titleElement = headElement.getElementsByTagName("title")[0]; if (titleElement != null) { // The text will be the first child node of the <title> element var titleText = titleElement.firstChild; // We can get the text of the text node with nodeValue alert("The page title is '" + titleText.nodeValue + "'"); } // After <head> is <body> var bodyElement = headElement.nextSibling; while (bodyElement.nodeName.toLowerCase() != "body") { bodyElement = bodyElement.nextSibling; } // We found the <body> element... // 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); } } } } |
目前虽然只看到了两个例子,清单 1 和 2,不过通过这两个例子您应该能够了解使用 DOM 树能够做什么。如果要尝试一下这些代码,只需要将 清单 3 拖入一个 HTML 文件并保存,然后用 Web 浏览器打开。
清单 3. 包含使用 DOM 的 JavaScript 代码的 HTML 文件
<html> <head> <title>JavaScript and the DOM</title> <script language="JavaScript"> function test() { // 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; // What's the name of the <html> element? "html" alert("The root element of the page is " + htmlElement.nodeName); // Look for the <head> element var headElement = htmlElement.getElementsByTagName("head")[0]; if (headElement != null) { alert("We found the head element, named " + headElement.nodeName); // Print out the title of the page var titleElement = headElement.getElementsByTagName("title")[0]; if (titleElement != null) { // The text will be the first child node of the <title> element var titleText = titleElement.firstChild; // We can get the text of the text node with nodeValue alert("The page title is '" + titleText.nodeValue + "'"); } // After <head> is <body> var bodyElement = headElement.nextSibling; while (bodyElement.nodeName.toLowerCase() != "body") { bodyElement = bodyElement.nextSibling; } // We found the <body> element... // 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); } } } } } </script> </head> <body> <p>JavaScript and DOM are a perfect match. You can read more in <i>Head Rush Ajax</i>.</p> <img src="http://www.headfirstlabs.com/Images/hraj_cover-150.jpg" /> <input type="button" value="Test me!" onClick="test();" /> </body> </html> |