文档对象模型(Doucment Object Model,DOM)是表示文档(如HTML文档、XML文档)和访问、操作构成文档的各种元素的应用程序接口。
在DOM中,HTML文档的层次结构被表示成树形结构。树的节点表示文档中的各种内容。DOM树形结构是各种类型的Node对象的树。Node接口为遍历和操作树定义了属性和方法。Node对象的childNodes属性将返回子节点的列表NodeList对象,firstChild、lastChild、nextSibling、previousSibling和parentNode属性提供了遍历树的方法。appendChild()、removeChild()、replaceChild(old,new)和insertBefore()方法,可以给文档树添加节点或从文档中删除节点。
(注意,在使用appendChild()方法时,如果参数是文档中已存在的节点,该方法会先从文档中去掉该节点)
文档树中不同类型节点由特定Node子接口表示,每个Node对象都有nodeType属性,指定节点的类型。常用节点类型:
接口 | nodeType常量 | nodeType值
Element | Node.ELEMENT_NODE | 1
Text | Node.TEXT_NODE | 3
Document | Node.DOCUMENT_NODE | 9
Comment | Node.COMMENT_NODE | 8
DocumentFragment | Node.DOCUMENT_FRAGMENT_NODE | 11
Attr | Node.ATTRIBUTE_NODE | 2
DOM树的根节点是个Document对象,它的documentElement属性引用表示文档根元素的Element对象。大部分DOM树由表示标记(如<html>和<i>)的Element对象和表示文本串的Text对象构成。
Element接口的getAttribute()方法、setAttribute()方法和removeAttribute()方法可以查询、设置和删除一个元素的性质。还可以调用getAttributeNode()方法(该方法使用不适很方便),返回一个表示性质和它的值的Attr对象(Attr接口定义了specified属性,可以判断文档中是否直接指定了该性质,或判断它的值是否是默认值)。但要注意,Attr对象不出现在元素的childNodes[]数组中,不像Element和Text节点那样是文档树的一部分。DOM标准允许通过Node接口的attributes[]数组访问Attr节点,但IE定义了不兼容的attributes[]数组。
DOM标准可以与XML文档和HTML文档一起使用。DOM的核心API(Node、Element、Document和其他接口)相对通用,可以应用于这两种类型的文档。DOM标准还包括HTML文档专有的接口(HTML***Element)。
DOM标准的HTML部分为其他所有HTML标记都定义了相应的接口。对大部分HTML标记来说,这些接口只是提供了一套镜像他们的HTML性质的属性集合。此外,某些接口还定义了其他的属性和方法(如HTMLFormElement接口定义了submit()和reset()方法及length属性)。
HTML专有DOM标准有一套命名规则,HTML专有接口的属性应该以小写字母开头,如果属性名有多个单词,第二个单词后的每个单词首个字母大写。当HTML性质名与JavaScript关键字发生冲突时,应在性质加前缀"html"来避免冲突。这个规则的一个例外是class性质,可以转化成HTMLElement的className属性。
DOM标准有两个版本(或说“级别”)。不同浏览器对DOM标准的支持程度有所不同,IE5以上版本支持使用HTML文档的基本1级DOM接口,Netscape支持2级DOM接口,如下代码可以检测浏览器支持的DOM接口级别:
if(document.implementation &&
document.implementation.hasFeature &&
document.implementation.hasFeature("html","1.0")){
....... //如果支持HTML DOM1级 执行
}
关于DOM标准的级别的资源:
W3C致力开发DOM实现的开放资源测试组,http://www.w3c.org/DOM/Test/
Mozilla组织测试套件,http://www.mozilla.org/quality/browser_sc.html
Netscape公司发布的测试套件,包括2级DOM的测试,http://developer.netscape.com/evangelism/tools/testsuites/
IE中的DOM一致性P335
DOM API提供了引用文档中元素的方法:
getElementsByTagName(var tagName),返回NodeList对象(NodeList对象行为与数组相似,我们可以认为这个函数返回一个以tagName指定的元素名组成的数组),它可以获得任何类型的HTML元素的列表。注意,因为HTML标记不区分大小写,所以传递给该方法的字符串也不区分大小写。如果把"*"传给getElementsByTagName()方法,将返回文档中所有元素的列表,顺序以在文档中出现的顺序。
getElementById(var id),该方法返回一个元素,该元素具有匹配的id属性。
(Document对象和Element对象都具有这两个方法)
Text节点的data域包含这个节点中所有字符串。document.createTextNode()方法可以创建新的Text节点。Text节点还可以用appendData()、insertData()、deleteData()和replaceData()方法添加、插入、删除或替换一个Text节点中的文本。
document.createElement(var eleName)方法可以创建新的<eleName>元素。
我们还可以调用element.setAttribute(),如**.setAttribute("align","center"),设置**的align属性值为center,它和**.align=center有同样的效果。
把任何元素的innerHTML属性设置为一个HTML文本串,都会使那段HTML被解析并插入以作为元素的内容。
DOM核心的API定义了DocumentFragment对象,作为使用Document节点组的快捷方法。DocumentFragment是一种特殊类型节点,它自身不出现在文档中,只作为连续节点集合的临时容器,并允许将这些节点作为一个对象来操作。当把一个DocumentFragment插入文档时(用Node对象的appendChild()、insertBefore()或replaceChild()),插入的不是DocumentFragment自身,而是它的所有子节点。如颠倒n节点顺序的reverse()方法:
function reverse(n){
var inputTag = n.childNodes;
var temp = document.createDocumentFragment();
while(n.lastChild){
temp.appendChild(n.lastChild);
}
n.appendChild(temp);
}
注意,在把DocumentFragment插入文档时,段的子节点移入文档中,插入后段是空的。
Traversal和Range API
Traversal API定义了遍历文档和筛选出用户不感兴趣节点的高级方法。Range API定义了操作连续范围内的文档内容的方法,即使那些内容不在节点的边界处开始或结束。