简介
一组平台和语言中立的 api ,能够描述如何访问和操纵存储在结构化 xml 和 html 中的信息, DOM 提供了一个标准的方法集来对文档元素添加,删除,修改和校验,以及文档结构的定位。 DOM 并不能显式规定数据如何被内部存储到应用程序,供应商可以自由使用它们认为最适合他们的数据的任何内部存储机制。 Dom 试图从应用程序用户的角度来描述数据如何被表示到外部世界。然后程序设计人员就可以向会泽县标准编写程序,而不是学习无数个应用程序提供商所提供的专有接口,这样可以提高程序的互操作性
设计原理
平台和语言中立
开放并且可扩展的
DOM 规范可以利用两种不同的方式窒息功能 xml/html 文档操纵指定接口:一种是传统的层次继承方式。另一种是简单的,平面化的方式。继承方式的工作原理正是优秀的面向对象程序员所期待的:接口类有层次结构。平面化的方式的观点是:所有的文档操作都可以用 Node 接口完成,并不需要程序员把节点引用转换为其他类型的对象
做出这个决定是因为对对象进行类型转换在某些编程环境中是一个开销很大的操作。然而 DOM working group 任务 api 的层次式视图是 DOM 的最主要的视图,而 NODE 接口的附加功能则作为开发人员选择使用的额外功能。规范中指出这会导致一些冗余。如尽管 node 接口有一个 nodename 属性,但在 element 接口仍然有一个 tagname 属性。这个两个属性值必须相同。
层
Dom 被组织为分离的层,每一层都提供自己的方法和定义。这些层可以定义一些本层用户希望从一个应用程序中获取的性能和服务。而这个应用程序则用以指出在哪个层中定义的 api 。
目前有两个正式的 DOM 层: level 1 和 level 2 ,这两个层都是 w3c 所推荐的
每个层都被分为两个或多个模块,每个层都通用的是 Core 模块,它可以指定处理结构化文档和对象需要的核心方法。其余的模块则着重处理那个特性层的具体特性。 DOM 应用程序可能会符合一个特定 dom 层,或符合一个 dom 层中的一个特定模块。例如, dom 中的 level1 指出两个模块, xml 和 html 。 Level2 可以把这个支持提高到 14 个以上。
Level 1
划分为两个模块, core 和 html 。 Core 模块提供一个方法集,用以访问和操作任何结构化文档中的文档对象,还提供一个扩展接口的集合用以处理 xml 内容。 Html 模块提高有一个高级接口,这个接口可以和 core 模块中的接口一起处理 html 文档,尽管仅仅使用 core 接口来处理 xml 和 html 已经足够了
这两个模块,提供了充分的功能,用于处理位于支持 api 的产品的已分析的 xml 和 html 文档,以及利用所提供的方法填充文档对象框架。创建文档对象并把它保存 / 加载到永久性存储器,或者从永久性存储器进行保存 / 加载都成为特定于应用程序的操作。
IE6 和 NETSCAPE6 的 dom level1 几乎完全支持。
Level 2
划分为 14 个截然不同的模块( core, XML, html, Range, Traversal , CSS , CSS 2 , Views , StyleSheets , Events , User Interface Events , Mouse Events , Mutation Events , HTML Events )并被组织在 5 个主要模块, Core, Views ,Events ,Style ,Traversal /Range
约定
在 IDL 中定义的属性并不表示具体对象必须具有特定的数据成员
DOM 应用程序可以提供这个规范不具备的额外接口和对象,并且这些接口和对象仍然被认为符合 DOM
由于我们指定的是接口,而不是要创建的真正对象,所以 DOM 无法获知对一个实现调用何种构造函数
DOM 规范没有规定多线程机制
基本数据类型
DOMString
描述一个字符序列,其中每个字符都表示为 16 位的单元。 UTF-16
特定语言绑定所使用的名称不同,如 java 语言使用 String 表示 DomString
通常需要把 DOMString 转换为本地字符串类型,但不是 dom 规范要求的
DOMTimeStamp
DOMException
DOM 节点类型
节点类型 | 说明 |
Element | 在 html 或 xml 文档中表示一个用标记表示的元素 |
Attribute | 表示一个元素的属性 |
Text | 表示一个元素的原文内容 |
CDATASection | 在 xml 文档中表示 Character Data (字符数据)部分 |
Comment | 表示一个注释,注释的表示形式为 <!—Comment text à |
Document | 表示文档的根节点 |
DocumentType | 每个文档节点都有一个 DocumentType 节点,提供一列定义在文档中的实体 |
DocumentFragment | 可以把文档片段看做轻量级或更小型的 Document 节点,定义这种数据类型因为通常希望只提取问到你个的一部分来处理 |
ProcessingInstruction | 表示一个文档处理程序使用的特有指令,在文档内容中可以将它用作一种保存特有处理程序信息的方法 |
Entity | 在 xml 文档中表示一个实体 |
EntityReference | 在文档中表示一个实体引用 |
Notation | 在 xml 文档中表示一个符号, notation 节点没有父节点 |
最重要的节点类型: Document , Element , Comment , Attribute , CDATA , Text
节点类型 | 允许的子节点类型 |
Document | Element( 至多一个 ) , ProcessingInstrution , Comment , DocumentType |
DocumentFragment | Element , ProcessingInstruction , Comment , Text , CDATASection , EntityReference |
DocumentType | 无 |
Element | Element , Text , Comment , ProcessingInstruction , CDATASection , EntityReference |
Comment | 无 |
Text | 无 |
Attribute | Text , EntityReference |
Entity | Element , ProcessingInstruction , Comment , Text , CDATASection , EntityReference |
CDATASection | Element , ProcessingInstruction , Comment , Text , CDATASection , EntityReference |
Notation | 无 |
导航和处理结构化文档
处理节点
命名空间
Level 1 不处理 xml 命名空间,在 level 2 添加了对命名空间的支持。
获得对节点的对象引用
Node 接口的 childNodes
Element 接口里面的 getElementsByTagName()
Document 接口里面的 getElementById()
检查节点
Document 节点的节点属性
节点属性 | 值 |
ownerDocument | NULL |
previousSibling | NULL |
nextSibling | NULL |
parentNode | NULL |
firstChild | Element(“HTML”) |
lastChild | Element(“HTML”) |
nodeName | “#document” |
nodeValue | null |
nodeType | 9(Document node) |
<TITLE> 标记的节点属性
节点属性 | 值 |
ownerDocument | Document node |
previousSibling | Null |
nextSibling | Comment node |
parentNode | Element node(“HEAD”); |
firstChild | TextNode |
lastChild | TextNode |
nodeName | “title” |
nodeValue | null |
nodeType | 1(Element node) |
处理节点
DOM 规范规定 firstChild ,lastChild ,parentNode , previousSibling , nextSibling 是只读的,通过 node 的接口修改文档中的节点顺序的唯一方式是,使用提供的方法, insertBefore() , appendChild () , replaceChild() , removeChild ()
创建新节点
使用工厂 (factory) 方法
Var obj = new SomeDocumentObject()
复制现有节点
Node 接口的 cloneNode()
从其他文档中导入节点
Dom level 2 api 提供了 importNode 方法
遍历文档
使用 node 接口属性
例子 :
function processNode (Node n){
If(n.nodeType != Node.ELEMENT_NODE){
Return ;
}
doStartNodeProcessing(n);
for(Node c= n.firstChild(); c!= null ; c= c.nextSibling()){
processNode( c ) ;
}
doEndNodeProcessing(n);
}
使用 DOM Level 2 的 Traversal 模块
四个接口: NodeIterator , NodeFilter ,TreeWalker ,DocumentTraversal
Iterator ,TreeWalker
NodeIterator 表示一种扁平的文档视图,节点以它们在文档中出现的顺序表示,不过缺少层次结构,所以只能向前移动或向后移动一列节点
TreeWalker 维持其文档层次结构
当你的 DOM 应用程序集中关注每个节点的内容时, iterator 更有用,当操纵子节点的结构时, Treewalker 更好
逻辑视图和物理视图
Iterator ,treewalker 可以表示文档子树的视图,而该文档子树可以不包含实际位于子树中的任何节点。 Dom Traversal 模块将这个称为逻辑视图
不依赖于 iterator ,treewalker 的真正文档子树是物理视图,通过把 Nodefilter 和 nodeiterator 后 treewalker 结合。
算法
1. 确定节点是否包含在另外一个节点里面
2. 确定节点是否有特定类型的兄弟节点
3. 寻找基于一个属性值的节点
4. 处理节点的子节点
遍历算法
深度优先
function processNode (Node n){
If(n.nodeType != Node.ELEMENT_NODE){
Return ;
}
doStartNodeProcessing(n);
for(Node c= n.firstChild(); c!= null ; c= c.nextSibling()){
processNode( c ) ;
}
doEndNodeProcessing(n);
}
宽度优先
function processNode (Node n){
doStartNodeProcessing(n);
if(n.hasChildNode())
{
for(Node c= n.firstChild(); c!= null ; c= c.nextSibling()){
// do child node processing here
}
for(Node c= n.firstChild(); c!= null ; c= c.nextSibling()){
processNode( c ) ;
}
}
doEndNodeProcessing(n);
}
主要浏览器中的 DOM 支持
随着 netscape2 和 ie3 对 js 的最初实现, web 创作人员可以给他们的网页添加一些交互性能,开发人员可以动态地修改文档内容,使图像指向新的 url ,检验窗体内容,已经完成更多的操作,这些都要通过一些简单的脚本代码和调整一个或者两个 html 标记的权限属性来完成。后拉的浏览器版本运行在超过一定时间周期后将层在屏幕周围移动并且提供简单的动画效果,虽然他还受到一定的限制,但是在当时来说,功能是非常强大的,当然不是所有的给定页面的所有属性都可以操作,一些浏览器相对其他浏览器提供更多的控制。
现在的浏览器从那时起已经有长足发展,现在使用 dom api 动态修改网页几乎任何部分(从样式表到页面本身真正结构和内容)的外观都是可能的。另外,因为 dom 提供了标准接口集来完成这些操作,所以通常情况下可以大大减少对特例代码的需要,这支持更为复杂的构建,启用用户界面,以及增强文档处理程序(跨多种顺应 dom 的浏览器工作)
Internet Explorer
Ie6 对 dom level 1 的 core 和 HTML 接口以及 css 1 提供了完整的支持
Ie6 支持 dom level 2 的 getElementByid()
NetScape
最新支持 Domlevel1 和部分 Domlevel2
脚本可以使用 dom 的功能,脚本可以发现页面的结构和内容,并且在运行时修改页面的内容
支持 dom level 2 events 模块