- 浏览: 1160759 次
文章分类
JavaScript 和文档对象模型(DOM)
2008 年 7 月 11 日 更新
虽然很多人都熟知文档对象模型(DOM)是处理 XML的基础,但使用 HTML 的浏览器开始使这个主题发生一些变化。随着更新的浏览器通过客户端脚本(比如 JavaScript)实现 W3C文档对象模型,现在 DOM 又经历了一个轮回。本文将介绍通过 JavaScript 实现 DOM,并描述 Web页面的构建,用户可以向这个页面添加并编辑注释。
注意:本文使用兼容 DOM 的浏览器,比如 Netscape 6.x、Internet Explorer 6 或 Mozilla 1.0。熟悉 Java 技术或其他语言的文档对象模型会有所帮助,但不是必要条件。不过您应该大体熟悉 JavaScript。
在本文中,我从文档对象模型的角度分析 Web页面的结构:检查子节点和父节点,以及向现有文档添加并编辑节点。为了演示这个过程,我将构建一个页面。用户可以在这个页面上任意创建注释并编辑这些注释的内容(这个页面不会很复杂;我将把一些任务留给您,比如保存和移动内容以及重新调整内容的大小等)。既然使用 DHTML技术就可以轻松实现这些操作,为什么还要使用 DOM 呢?
开发 XML 的其中一股推动力是将 HTML 片段化,而 DHTML 顺应了这一潮流。虽然某些方面已经形成标准,但浏览器如何处理不同的方面仍然存在很大的分歧。DOM 是可以在整个领域范围内实现的标准接口集,因此编程人员只需编写一个版本的页面。
另外,Web 页面不断朝 XML 的方向发展。XHTML 1.0 只是由 HTML 4.0.1 改编而来的 XML,并且也越来越多地使用 XML 生成 Web 页面。最终,DOM 将是在这些页面内访问元素和文本的主要技术(也可将它用于 XSLT 样式表)。
|
|
让我们从基础的页面开始,该页面包含一个工作区域和表单,它显示了已创建注释的数量:
<html> <head> <title>Getting Sticky</title> <style type="text/css"> * {font-family: sans-serif} a {font-size: 6pt} .editButton {font-size:6pt} </style> </head> <body> <div id="mainDiv" style="height:95%; width:95%; border:3px solid red; padding: 10px;"> <h1>Getting Sticky</h1> <form id="noteForm"> Current number of notes: <input type="text" name="total" value="0" size="3"/> <input type="button" value="Add a new note"/> </form> </div> </body> </html> |
清单 1 展示了带有几种样式(只是为了使页面好看些)的基础页面。页面的正文包括一个单个的
div
元素,该元素包含一个 heading 元素(h1
)和一个 form
元素。即使是在没有使用 DOM 的浏览器里,也可以在表单内访问信息。
|
|
使用 DHTML 可以访问甚至修改表单字段的信息。例如,您可以创建一个脚本将当前表单的值增加 1,然后告诉页面在用户点击按钮时执行这个脚本:
<html><head> <title>Getting Sticky</title> <style type="text/css"> * {font-family: sans-serif} a {font-size: 6pt} .editButton {font-size:6pt} </style> <script type="text/javascript"> function incrementCurrent() { current = parseInt(document.forms["noteForm"].total.value); document.forms["noteForm"].total.value = current + 1; } </script> </head><body> <div id="mainDiv" style="height:95%; width:95%; border:3px solid red; padding: 10px;"> <h1>Getting Sticky</h1> <form id="noteForm"> Current number of notes: <input type="text" name="total" value="0" size="3"/> <input type="button" value="Add a new note" onclick="incrementCurrent()"/> </form> </div> </body></html> |
在
清单 2 中,incrementCurrent()
函数接受文档对象,然后将 noteForm
对象从页面内的表单数组中抽出。该函数从
noteForm
对象获得表单字段 total
并检索值,然后在页面内更新这个值。
这种更改是即时的。更改页面、重新加载并反复按按钮,您将发现文本字段每一次都会相应地进行更新。
同样,您也可以使用 DHTML 属性检索 div
元素的文本。由于它有一个 mainDiv
的
id
,因此可以使用 innerHTML
属性,如:
theText = mainDiv.innerHTML;
在这个例子中,使用了两个 DHTML 技术:forms
数组,以及通过基于属性值的名称调用元素(而不是通过元素名或总体结构)。但存在的问题是这种方法不够通用。虽然可以对表单的名称使用一个变量,如果碰到不使用表单的呈现,应该怎么办呢?
|
|
如果存在一个定义文档对象模型的原则,它将把信息排列成父-子层次结构。例如,参看以下的 XML:
<parentElement><childElement>My Text Node</childElement></parentElement>
有 3 个节点:root 节点是 parentElement
。它有一个子元素 childElement
。childElement
元素有自己的父元素
parentElement
,作为子元素的文本节点的值是 “My Text Node”。这个文本节点的父元素是 childElement
。共享一个父元素的两个节点称为兄弟(sibling)节点。注意,文本就是它本身的节点。元素实际上并没有值,它们仅有文本子节点。
您应该比较熟悉如何使用 Java 技术或其他语言读取 XML 文档的结构。实施这个操作要用到一个带有定义良好的函数和对象属性的 API。例如,这个文档有一个作为其根元素的
html
元素,该元素有两个子元素 head
和 body
(为简单起见,我删除了正常情况下会出现在这些元素之间的空格;至于如何处理这些空格,不同的浏览器之间还没有达成一致)。要通过 Java 技术访问
body
元素,您可以使用几个不同的表达式,假如您已经命名了 Document
对象 document
。
第一个步骤是获得所有元素的子元素的列表,然后从该列表选择一个特定的条目,就像以下的例子一样:
bodyElement = document.getChildNodes().item(0).getChildNodes().item(1);
在这里,首先获得 html
元素(该元素是文档的第一个子元素),然后获得它的第二个子元素 body
(getChildNodes()
是基于零的)。另一种办法是将
html
元素作为第一个子元素直接访问,然后移动到它的第一个子元素(head
),最后移动到该元素的下一个兄弟元素(第二个子元素
body
):
bodyElement = document.getFirstChild().getFirstChild().getNextSibling();
从这里您可以获得节点的类型:
typeInt = bodyElement.getNodeType()
节点类型以整数返回,并且允许您适当地处理每一个节点;一个元素(类型 1
)有名称没有值,但是一个文本节点(类型 3
)有值没有名称。
了解了这些后,就可以获取元素的名称:
elementName = bodyElement.getNodeName();
或它的文本内容:
elementContent = bodyElement.getFirstChild().getNodeValue();
(记住,元素的文本本身就是一个节点,而该元素则是它的父节点)。
当将这些函数移动到 JavaScript 时,相同的基本 API 已经准备就绪,但处理方式有些不同。例如,可以直接访问属性,而不是通过 get
和
set
方法访问,因此 JavaScript 中的相同语句会表示为:
bodyElement = document.childNodes.item(0).childNodes.item(1);
bodyElement = document.firstChild.firstChild.nextSibling;
您可以从这里获得元素的类型和名称及其内容:
ElementType = bodyElement.nodeType;
elementName = bodyElement.nodeName;
elementContent = bodyElement.firstChild.nodeValue;
但是需要注意,只能更改属性的名称。返回对象的函数保持不变。例如,可以根据 ID 检索某个特定的对象,就像下面的示例一样:
formElement = document.getElementById("noteForm");
这只是基本原理,现在我们看看它的实际运行情况。
|
|
实际节点本身只是一个带有标准文本和链接的框,这个框允许用户稍后再编辑文本,如 图 2 所示。
这个新节点与下面的 HTML 等效:
<div id="note1" style="width: 100; height:100; border: 1px solid blue; background-color: yellow; position: absolute; top: 150; left: 135"> <a href="javascript:editNote('note1')">edit</a> <br /> New note </div> |
使用标准的 DOM 添加实际元素,如 清单 4 所示:
<html> <head> <title>Getting Sticky</title> <style type="text/css"> * {font-family: sans-serif} a {font-size: 6pt} .editButton {font-size:6pt} </style> <script type="text/javascript"> ... function getCurrentNumber() { formElement = document.getElementById("noteForm"); return formElement.childNodes.item(1).value; } function makeNewNote(){ mainDivElement = document.getElementById("mainDiv"); newNote = document.createElement("div"); newNote.setAttribute("id", "note"+getCurrentNumber()); mainDivElement.appendChild(newNote); incrementCurrent(); } </script> </head> <body> <div id="mainDiv" style="height:85%; width:85%; border:3px solid red; padding: 10px; z-index: -100" > <h1>Getting Sticky</h1> <form id="noteForm"> Current number of notes <input type="text" name="total" value="0" size="3"/> <input type="button" value="Add a new note" onclick="makeNewNote()"/> </form> </div> </body> </html> |
在这个示例中,更改了按钮从而执行 makeNewNote()
而不是 incrementCurrent()
,尽管
makeNewNote()
还使用该函数。首先,通过 getElementById()
获得针对主元素
div
的引用,这个元素最终会包含注释。然后可以使用 document
对象创建一个名为 div
的新元素,就像在其他语言中一样。要设置
id
属性,您只需要在新的元素上使用 setAttribute()
方法。
每一个注释都有一个独特的 id
属性,因此您需要知道当前的总和是多少。要获得这个信息,必须从 form 元素本身开始。可以从这里获取子元素列表。第一个(带有一个索引
0
)是文本,第二个是(带有一个索引 1
)是实际的 input
元素。
但 .value
又是什么呢?是不是输入错误?它应该是 nodeValue
,是吗?
实际上不是。记住,元素没有值。乍一看,好像我将 DOM 和 DHTML 属性混在一起,但实际上现在获取的元素不仅是 org.w3c.dom.Element
的实现,还是
org.w3c.dom.html.HTMLInputElement
(它也包含了一个代表表单字段值的值属性)的实现。在这一方面,DOM 模仿了一些(虽然不是全部)通过 DHTML 可以实现的属性。
设置了属性之后,只需要将新的 div
元素附加到 mainDiv
元素,div
元素将出现在这个位置上。或者,如果它有任何显示属性或文本的话,它至少会出现在这个位置上。
要添加样式信息,将需要实际使用 DHTML 样式对象:
...
function makeNewNote(){
mainDivElement = document.getElementById("mainDiv");
newNote = document.createElement("div");
newNote.setAttribute("id", "note"+getCurrentNumber());
newNote.style.width="100";
newNote.style.height="100";
newNote.style.border="1px solid blue";
newNote.style.backgroundColor="yellow";
newNote.style.position="absolute";
newNote.style.top=(150);
newNote.style.left=(25 + 110*getCurrentNumber());
mainDivElement.appendChild(newNote);
incrementCurrent();
}
...
|
添加的结果是产生一个蓝边的黄色小框,如 图 3 所示。
注意,注释的 left
属性取决于当前注释的数量,它随着每个注释的添加而增长。您可以通过这种方式添加一系列框,如
图 3 所示。
|
|
添加 div
的内容会呈现一个小问题。我可以使用 innerHTML 属性:
newNote.innerHTML = "<a href=/"javascript:editNote('note" +getCurrentNumber()+")/">edit</a><br />New note"; |
但我如何直接使用 DOM 方法来实现?首先想到的可能是简单地设置 div
元素的文本子节点的值:
noteText = document.createTextNode( "<a href=/"javascript:editNote('note"+getCurrentNumber()+")/">"+ "edit</a><br />New note"); newNote.appendChild(noteText); |
虽然文本真的得到了添加,但结果可能与预期不同,如 图 4 所示。
问题是您并没有真的添加文本,而是混合了内容,包括文本和元素。浏览器认为您将这看作是 CDATA(完全按照字面意义得出),并且也没有创建元素。不是简单地在一个块中添加所有的内容,您必须实际添加每个元素:
... function makeNewNote(){ mainDivElement = document.getElementById("mainDiv"); newNote = document.createElement("div"); newNote.setAttribute("id", "note"+getCurrentNumber()); ... editLink = getEditLink("note"+getCurrentNumber()); newNote.appendChild(editLink); newNote.appendChild(document.createElement("br")); noteText = document.createTextNode("New Form"); newNote.appendChild(noteText); mainDivElement.appendChild(newNote); incrementCurrent(); } function getEditLink(thisId){ editLink = document.createElement("a"); linkText = document.createTextNode("edit"); editLink.setAttribute("href", "javascript:editNote('"+thisId+"')"); editLink.appendChild(linkText); return editLink; } ... |
首先,您已经创建了一个返回一个对象的新函数 getEditLink
。这个对象是用标准 DOM 方法创建的 a
元素。接下来,添加一个标准的 break 标记
br
,最后添加包含实际节点文本的节点。
结果是得到完成的节点,而元素保持完整并可使用。
|
|
现在有了内容,但怎样才能更改它呢?因为您单个地添加元素,所以只能编辑代表节点文本的单个文本节点。这可以通过 3 种方式来实现。首先删除有问题的节点,然后添加一个新的节点:
... function editNote(editLink){ theDiv = document.getElementById(editLink); newText = prompt("What should the note say?"); oldNode = theDiv.firstChild.nextSibling.nextSibling; theDiv.removeChild(oldNode); newNode = document.createTextNode(newText); theDiv.appendChild(newNode); } ... |
另一种方法很简单,只需代换现有的节点:
... function editNote(editLink){ theDiv = document.getElementById(editLink); newText = prompt("What should the note say?"); oldNode = theDiv.firstChild.nextSibling.nextSibling; newNode = document.createTextNode(newText); theDiv.replaceChild(newNode, oldNode); } ... |
在这个示例中,用 newNode
代替了 oldNode
,同时也相应地更改了文档。
最后一个办法是更改现有节点的文本:
... function editNote(editLink){ theDiv = document.getElementById(editLink); newText = prompt("What should the note say?"); theDiv.firstChild.nextSibling.nextSibling.nodeValue=newText; } ... |
因为 editNote
使用相应的 div
的 id
值作为参数,相同的函数可以用于任意节点,如
图 5 所示。
|
|
在本文,您已经了解在 Web 页面的 JavaScript 中使用 DOM 的基础知识。您可以在使用 JavaScript 的地方(比如在 XSLT 样式表中)使用这些基本原理。
文档对象模型将 XML 文档内的元素、文本和其他类型的节点呈现为一系列的父子关系。操作这些单独的节点可以影响页面本身。除了 DOM Core方法以外,XHTML 页面也可以公开作为 DOM HTML 模块的一部分的属性和方法,DOM HTML 模块试图整合许多编程人员用了好几年的DHTML 属性。
相关推荐
Javascript文档对象模型(DOM)
JavaScrip入门教程 文档对象模型(DOM)
为了能够操纵浏览器和文档,JavaScript使用分层的父对象和子对象,这就是“文档对象模型”。这些对象的组织类似一个树型结构,并表示一个Web文档的所有内容和组件。 注意:”文档对象模型”不是JavaScript语言的一...
开发工具与关键技术:Adobe Dreamweaver JavaScript 文档对象模型知识点总结
JavaScript中BOM和DOM详解 目录 BOM(浏览器对象模型) 1. window 获取浏览器c窗口尺寸 2. screen 获取电脑屏幕大小 3. window 开启关闭窗口 4. 浏览器事件 5. location 6. history 7. navigator 获取浏览器相关...
什么是DOM DOM的全称是Document Object Model,即文档对象模型,它允许脚本控制Web页面、窗口和文档。 如果没有DOM,JavaScript将是另外一种脚本语言;而有了DOM,它将成为制作动态页面的强有力工具。DOM不是...
javascript中的高阶部分,是window对象的使用,而windows对象使用与Dom密切相关,了解它的层次模型显得很重要
骰子游戏 这是一个简单的交互式站点,它使用基本的 JavaScript 和文档对象模型 (DOM)
第三章:javascript-DOM对象模型-补充课件.ppt
第5章 文档对象模型 DOM 第6章 String Math Array等数据对象 第7章 Window及相关顶级对象 第8章 Document对象">该资源为8个PDF文档教程 适合JS开发初学者 具体内容为 第1章 JavaScript语言概述 第2章 JavaScript...
从颇具深度的JavaScript语言基础到作用域(链),从引用类型到面向对象编程,从极其灵活的匿名函数到闭包的内部机制,从浏览器对象模型(BOM)、文档对象模型(DOM)到基于事件的Web脚本设计,从XML(E4X)到Ajax及JSON,从...
第一讲_第5课__JavaScript_DOM对象模型编程
2.7.1 内建对象 2.7.2 宿主对象 2.8 小结 第3章 DOM 3.1 文档:DOM中的"D" 3.2 对象:DOM中的"O" 3.3 模型:DOM中的"M" 3.4 节点 3.4.1 元素节点 3.4.2 文本节点 3.4.3 属性节点 3.4.4 CSS 3.4.5 获取元素 3.4.6 盘点...
Dom:英文全称-Document Object Model 译成中文即是:文档对像模型.听起来很术语,其实就是文档内容的结构关系.文档类型可以是HTML或XML Dom具有对Html文件和XML文件元素的访问控制能力,简单点说利用Dom可以对...
接第2章 JavaScript基础,请关注
文档对象模型(DOM)是HTML和XML文档的编程接口。 它代表页面,以便程序可以更改文档的结构,样式和内容。 ... DOM是网页的面向对象的表示形式,可以使用诸如JavaScript之类的脚本语言进行修改。
比较不错的js dom手册, 方便查阅各种dom方法
DOM文档对象模型是HTML和XML的应用程序接口(API),DOM将整个页面规划成由节点层次构成的文档。DOM对象给予开发者对HTML的访问权限,并且使开发者能将HTML作为XML文档来处理和查看。DOM对象是与语言无关的API,意味...
本书分4篇14章,介绍Javascript的知识,全书内容包括:Javascript语法基础、流程控制、函数、内置对象编程、文档对象模型DOM与事件驱动、处理XML、使用Cookie和文件、应用Ajax技术等。本书最后一篇从6个...