HTML中的DOM 1级模型

DOM

DOM(文档对象模型)是针对HTML和XML文档的一个API,描绘了层次化的节点树。开发者可以借助DOM对页面的某一部分进行添加、移除、修改。DOM来源于网景和微软提出的DHTML。1998年10月,DOM 1级规范称为W3C的标准,为文档查询和改动提供了接口。各大主流浏览器都完善地实现了DOM。


DOM把HTML和XML文档描述成一个多层节点构成的结构。每个节点有都有自己的特点、数据和方法。

文档节点是每个文档的根节点。HTML中<html>元素是文档节点唯一的子节点,又称为文档元素。每一个标签都通过树中的一个节点表示,HTML元素表示为元素节点,特性通过特性节点表示,文档表示为文档节点,如此这样,总共有12中节点类型。

Node

DOM 1级中定义了Node类型。JavaScript中的所有节点类型都继承于Node类型。每个节点都有一个nodeType属性。常用的取值如下:

  • Node.ELEMENT_NODE(1)
  • Node.ATTRIBUTE_NODE(2)
  • Node.TEXT_NODE(3)
  • Node.COMMENT_NODE(8)
  • Node.DOCUMENT_NODE(9)
  • Node.DOCUMENT_TYPE_NODE(10)
  • Node.DOCUMENT_FRAGMENT_NODE(11)

为了确保浏览器兼容性,建议还是将nodeType属性和数字值进行比较,减少使用常量。因为IE没有公开Node类型的构造函数。

1
2
3
if (someNode.nodeType == 1) { // 元素节点
alert("This is an element node.");
}

除了nodeType,节点类型还有nodeNamenodeValue两个属性。它们的取值取决于节点的类型。后面的介绍中也会提到。

节点关系

在父子关系上,每个节点有一个childNodes属性,保存着NodeList对象。这个对象有length属性,也可以通过方括号访问其中的值,也可以通过item()方法访问,但它并不是Array的实例。且DOM结构的变化会实时地反映到这个NodeList对象中。减少使用NodeList可以避免它带来的时延

使用firstChildlastChild属性可以分别访问到列表中第一个和最后一个节点。同时,每个节点都有一个parentNode属性,指向文档树的父节点。

在兄弟关系上,使用nextSiblingpreviousSibling分别可以访问到下一个和上一个兄弟节点。hasChildNodes()在节点包含多个子节点时返回true。

最后,所有节点都有ownerDocument属性,指向整个文档的文档节点。

节点操作

appendChildinsertBefore分别用于在childNodes末尾和某位前插入节点。并返回插入的DOM节点。需要注意的是,如果插入的节点来自于DOM中,则节点会从原来的位置删除

1
2
3
var returnedNode = someNode.appendChild(newNode);
var anotherNode = someNode.insertBefore(newNode, null); // 插入到最后一位
anotherNode = someNode.insertBefore(newNode, someNode.firstChild); // 插入到第二位

replaceChild用于替换节点,cloneChild用于复制节点,cloneChild方法接受一个布尔值参数,表示是否执行深复制。在参数为true时执行深复制,否则执行浅复制。

需要留意的是,`cloneChild`不会复制DOM节点中的JavaScript属性,如事件处理程序。IE则会复制事件处理程序。为了保证一致性,建议在复制前移除事件处理程序。

最后,节点的normalize方法可以删除节点后代中的空文本节点,合并相邻的文本节点。

Document

JavaScript中用Document类型表示文档,浏览器中的document表示整个页面。它是window对象的一个属性。因此可以作为全局对象来访问。

它的nodeType为9,nodeName为"#document",子节点可以是一个DocumentType或Element类型的节点。在HTML中可以通过documentElement属性便捷地得到子节点<html>。所有浏览器都支持这个属性。document.body属性也都被支持。

除了<html>,另一个可能的子节点是DocumentType,即<!DOCTYPE>标签。浏览器对它的支持差异很大。同样的还有<html>元素外的注释。

document还有下面4个独特的HTML属性:

  • title包含网页的标题,属性的修改直接对应<title>元素
  • URL表示页面的URL,只读
  • domain表示页面的域名,可修改
  • referer保存链接到当前页面的URL,只读

其中修改domain可以用来访问同一父级域名下的iframe中的资源。

为了保证安全,域名修改只能由“紧绷”变“松散”,而不能反过来。

查找元素

DOM 1级标准只有getElementById()getElementsByTagName()getElementsByName()三种方法。具体功能不必再提。它们返回的是一个HTMLCollection对象。这个对象和NodeList很类似。同样可以通过方括号访问其中的子元素。不过HTMLCollection额外提供namedItem()方法,通过name属性值访问其中的子元素。

除此以外,document对象还有一个特殊的集合,它们也都是HTMLCollection对象。如document.anchorsdocument.formsdocument.imgsdocument.links

其他

document.implementation属性用来检测浏览器对DOM实现的程度,它有一个hasFeature()

write()writeln()open()close()方法可以将输出流写入到网页中。

Element

除了document外,Element类型应该是HTML中最常用的类型了。它的nodeType为1,nodeName为元素的标签名,tagName属性也可以用来访问元素标签名。

所有HTML元素都由HTMLElement的子类型表示。所有的HTML元素都具有下面的一些标准特性:

  • id:元素的唯一标识符
  • title:有关元素的附加说明信息
  • lang:元素的语言代码
  • dir:语言的方向
  • className:与元素的class对应

这些都可以通过访问元素的属性得到。如:

1
<div id="myDiv" class="foo" title="text" lang="en" dir="ltr"></div>

元素的信息可以通过下面的方式得到,同样,这些属性可以直接赋予新值来修改。

1
2
3
4
5
6
var div = document.getElementById("myDiv");
console.log(div.id);
console.log(div.class);
console.log(div.title);
console.log(div.lang);
console.log(div.dir);

未完待续