《 JavaScript高级程序设计》第六章DOM基础知识介绍
《 JavaScript高级程序设计》第六章DOM基础知识介绍
截取自读书频道:
http://book.csdn.net/bookfiles/110/index.htm
6.1 什么是DOM?
在开始详细介绍什么是DOM之前,你首先要了解是什么促使了它的诞生。尽管DOM很大程度上受到浏览器中动态HTML发展的影响,但W3C还是将它最先应用于XML。
6.1.1 XML简介
XML(可扩展标记语言)是从称为SGML(标准通用标记语言)的更加古老的语言派生出来的。SGML的主要目的是定义使用标签来表示数据的标记语言的语法。
XML去掉了之前令许多开发人员头疼的SGML的随意语法。
1 任何的起始标签都必须有一个结束标签。
2 可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号之前紧跟一个斜线(/),例如<tag />。XML解析器会将其翻译成<tag></tag>。
3 标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签,例如<b>this is a <i>sample</i> string</b>4 所有的特性都必须有值。
5 所有的特性都必须在值的周围加上双引号。
xml的主要目的是使用文本以结构化的方式来表示数据。在某些方面,XML文件也类似于数据库,提供数据的结构化视图。
每个XML文档都由XML序言开始,在前面的代码中的第一行便是XML序言,<?xml version="1.0"?>。
第二行代码,<books>,则是文档元素(document element),它是文件中最外面的标签(我们认为元素(element)是起始标签和结束标签之间的内容)。
然后其中的具体内容就可能包括注释,处理指令,<![CDATA[ ]]>代码.
6.1.2 针对XML的API
将XML定义为一种语言之后,就出现了使用常见的编程语言(如Java)来同时表现和处理XML代码的需求。
首先出现的是Java上的SAX(Simple API for XML)项目。SAX提供了一个基于事件的XML解析的API。从其本质上来说,SAX解析器从文件的开头出发,从前向后解析,每当遇到起始标签或者结束标签、特性、文本或者其他的XML语法时,就会触发一个事件。然后,当事件发生时,具体要怎么做就由开发人员决定。
DOM是针对XML的基于树的API。它关注的不仅仅是解析XML代码,而是使用一系列互相关联的对象来表示这些代码,而这些对象可以被修改且无需重新解析代码就能直接访问它们。DOM是语言无关的API,他没有与某种语言绑定。
6.1.3 节点的层次
DOM定义了Node的接口以及许多种节点类型来表示XML节点的多个方面:
1 Document——最顶层的节点,所有的其他节点都是附属于它的。
2 DocumentType——DTD引用(使用<!DOCTYPE >语法)的对象表现形式,例如<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">。它不能包含子节点。
3 DocumentFragment——可以像Document一样来保存其他节点。
4 Element——表示起始标签和结束标签之间的内容,例如<tag></tag>或者<tag/>。这是唯一可以同时包含特性和子节点的节点类型。
5 Attr——代表一对特性名和特性值。这个节点类型不能包含子节点。
6 Text——代表XML文档中的在起始标签和结束标签之间,或者CData Section内包含的普通文本。这个节点类型不能包含子节点。
8 CDataSection——<![CDATA[ ]]>的对象表现形式。这个节点类型仅能包含文本节点Text作为子节点。
9 Entity——表示在DTD中的一个实体定义,例如<!ENTITY foo "foo">。这个节点类型不能包含子节点。
10 EntityReference——代表一个实体引用,例如"。这个节点类型不能包含子节点。
11 ProcessingInstruction——代表一个PI。这个节点类型不能包含子节点。
12 Comment——代表XML注释。这个节点类型不能包含子节点。
13 Notation——代表在DTD中定义的记号。这个很少用到,所以在本书中不会讨论。
Node接口定义了对应不同节点类型的12个常量(它们会在即将讨论的nodeType特性中使用到):
1 Node.ELEMENT_NODE (1)
2 Node.ATTRIBUTE_NODE (2)
3 Node.TEXT_NODE (3)
4 Node.CDATA_SECTION_NODE (4)
5 Node.ENTITY_REFERENCE_NODE (5)
6 Node.ENTITY_NODE (6)
7 Node.PROCESSING_INSTRUCTION_NODE (7)
8 Node.COMMENT_NODE (8)
9 Node.DOCUMENT_NODE (9)
10 Node.DOCUMENT_TYPE_NODE (10)
11 Node.DOCUMENT_FRAGMENT_NODE (11)
12 Node.NOTATION_NODE (12)
Node接口也定义了一些所有节点类型都包含的特性和方法。我们在下面的表格中列出了这些特性和方法:
特性/方法 |
类型/返回类型 |
说 明 |
nodeName |
String |
节点的名字;根据节点的类型而定义 |
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 |
Node |
将childNodes中的oldnode替换成newnode |
insertBefore |
Node |
在childNodes中的refnode之前插入newnode |
除节点外,DOM还定义了一些助手对象,它们可以和节点一起使用,但不是DOM文档必有的部分。
1 NodeList——节点数组,按照数值进行索引;用来表示一个元素的子节点。
2 NamedNodeMap——同时用数值和名字进行索引的节点表;用于表示元素特性。
6.1.4 特定语言的DOM
任何基于XML的语言,如XHTML和SVG,因为它们从技术上来说还是XML,仍然可以利用刚刚介绍的核心DOM。然而,很多语言会继续定义它们自己的DOM来扩展XML核心以提供语言的特色功能。
6.2 对DOM的支持
并不是所有的浏览器对DOM的支持都一样。一般来说,Mozilla对DOM标准支持最好,这个领域中落在最后的是IE,它对DOM Level 1的实现都还不完整,尚有很多方面有待完善。
6.3 使用DOM
document对象是BOM的一部分,同时也是HTML DOM的HTMLDocument对象的一种表现形式,反过来说,它也是XML DOM Document对象6.3.1 访问相关的节点
在下面的几节中考虑下面的HTML页面:
要访问<html/>元素(你应该明白这是该文件的document元素),你可以使用document的documentElement特性:
var oHtml = document.documentElement;
现在变量oHtml包含一个表示<html/>的HTMLElement对象。如果你想取得<head/>和<body/>元素,下面的可以实现:
也可以使用childNodes特性来完成同样的工作。只需把它当成普通的JavaScript Array,使用方括号标记:
你还可以通过使用childNodes.length特性来获取子节点的数量:
注意方括号标记其实是NodeList在JavaScript中的简便实现。实际上正式的从childNodes列表中获取子节点的方法是使用item()方法:
HTML DOM页定义了document.body作为指向<body/>元素的指针:
有了oHtml、oHead和oBody这三个变量,就可以先尝试确定它们之间的关系:
这一小段代码测试并验证了oBody和oHead的parentNode特性都是指向oHtml变量,同时使用previousSibling和nextSibling特性来建立它们之间的关系。最后一行确认了oHead的ownerDocument特性事实上是指向该文档。
6.3.2 检测节点类型
我们可以通过使用nodeType特性检验节点类型:
这个例子中,document.nodeType返回9,等于Node.DOCUMENT_NODE;同时document. documentElement.nodeType返回1,等于Node.ELEMENT_NODE。
也可以用Node常量来匹配这些值:
这段代码可以在Mozilla 1.0+、Opera 7.0+和Safari 1.0+上正常运行。不幸的是,IE不支持这些常量,所以这些代码在IE上会产生错误。所幸,可以通过定义匹配节点类型的常量来纠正这种情况,正如下面这样:
6.3.3 处理特性
只有Element节点才能有特性。Element节点的attributes属性其实是NamedNodeMap,它提供一些用于访问和处理其内容的方法:
1 getNamedItem(name)——返回nodeName属性值等于name的节点;
2 removeNamedItem(name)——删除nodeName属性值等于name的节点;
3 setNamedItem(node)——将node添加到列表中,按其nodeName属性进行索引;
4 item(pos)——像NodeList一样,返回在位置pos的节点;
NamedNodeMap对象也有一个length属性来指示它所包含的节点的数量。
当NamedNodeMap用于表示特性时,其中每个节点都是Attr节点,它的nodeName属性被设置为特性名称,而nodeValue属性被设置为特性的值。例如,假设有这样一个元素:
同时,假设变量oP包含指向这个元素的一个引用。于是可以这样访问id特性的值:
还可以通过给nodeValue属性赋新值来改变id特性:
Attr节点也有一个完全等同于(同时也完全同步于)nodeValue属性的value属性,并且有name属性和nodeName属性保持同步。我们可以随意使用这些属性来修改或变更特性。
因为这个方法有些累赘,DOM又定义了三个元素方法来帮助访问特性:
q