上一期中 Brett 介绍了文档对象模型(DOM),它的元素在幕后定义了 Web 页面。这一期文章中他将进一步探讨 DOM。了解如何创建、删除和修改 DOM 树的各个部分,了解如何实现网页的即时更新!
如果阅读过本系列的 上一期文章,那么您就非常清楚当 Web 浏览器显示网页时幕后发生的一切了。前面已经提到,当 HTML 或为页面定义的 CSS 发送给 Web 浏览器时,网页被从文本转化成对象模型。无论代码简单或复杂,集中到一个文件还是分散到多个文件,都是如此。然后浏览器直接使用对象模型而不是您提供的文本文件。浏览器使用的模型称为文档对象模型(Document Object Model,DOM)。它连接表示文档中元素、属性和文本的对象。HTML 和 CSS 中所有的样式、值、甚至大部分空格都合并到该对象模型中。给定网页的具体模型称为该页面的 DOM 树。
了解什么是 DOM 树,以及知道它如何表示 HTML 和 CSS 仅仅是控制 Web 页面的第一步。接下来还需要了解如何处理 Web 页面的 DOM 树。比方说,如果向 DOM 树中增加一个元素,这个元素就会立即出现在用户的 Web 浏览器中 —— 不需要重新加载页面。从 DOM 树中删除一些文本,那些文本就会从用户屏幕上消失。可以通过 DOM 修改用户界面或者与用户界面交互,这样就提供了很强的编程能力和灵活性。一旦学会了如何处理 DOM 树,您就向实现丰富的、交互式动态网站迈出了一大步。
注意,下面的讨论以上一期文章 “利用 DOM 进行 Web 响应” 为基础,如果没有阅读过那一期,请在继续阅读之前首先阅读上一期文章。
首字母缩写的拼读问题
跨浏览器、跨语言
文档对象模型是一种 W3C 标准(链接参见 参考资料)。因此,所有现代 Web 浏览器都支持 DOM —— 至少在一定程度上支持。虽然不同的浏览器有一些区别,但如果使用 DOM 核心功能并注意少数特殊情况和例外,DOM 代码就能以同样的方式用于任何浏览器。修改 Opera 网页的代码同样能用于 Apple's Safari?、Firefox?、Microsoft? Internet Explorer? 和 Mozilla?。
DOM 也是一种跨语言 的规范,换句话说,大多数主流编程语言都能使用它。W3C 为 DOM 定义了几种语言绑定。一种语言绑定就是为特定语言定义的让您使用 DOM 的 API。比如,可以使用为 C、Java 和 JavaScript 定义的 DOM 语言绑定。因此可以从这些语言中使用 DOM。还有几种用于其他语言的语言绑定,尽管很多是由 W3C 以外的第三方定义的。
本系列文章主要讨论 JavaScript 的 DOM 绑定。这是因为多数异步应用程序开发都需要编写在 Web 浏览器中运行的 JavaScript 代码。使用 JavaScript 和 DOM 可以即时修改用户界面、响应用户事件和输入等等 —— 使用的完全是标准的 JavaScript。
总之,建议您也尝试一下其他语言中的 DOM 绑定。比如,使用 Java 语言绑定不仅能处理 HTML 还可处理 XML,这些内容将在以后的文章中讨论。因此本文介绍的技术还可用于 HTML 之外的其他语言,客户端 JavaScript 之外的其他环境。
清单 1. 使用 DOM 中的节点属性
// 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.
}
清单 2. 使用 DOM 中的节点方法
// 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;
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;
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>