DOM(文档对象模型)是针对HTML和XML文档的一个API(应用程序编程接口)。DOM描绘了一个层次变化的节点树,允许开发人员添加、移除和修改页面的某一部分。
一、节点层次
在HTML页面中,文档元素始终都是<html>
元素。
1. Node类型
javascript中的所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法。
(1)nodeType属性:用于表明节点的类型。
常量 | 值 |
---|---|
Node.ELEMENT_NODE | 1 |
Node.ATTRIBUTE_NODE | 2 |
Node.TEXT_NODE | 3 |
Node.CDATA_SECTION_NODE | 4 |
Node.ENTITY_REFERENCE_NODE | 5 |
Node.ENTITY_NODE | 6 |
Node.PROCESSING_INSTRUCTION_NODE | 7 |
Node.COMMENT_NODE | 8 |
Node.DOCUMENT_NODE | 9 |
Node.DOCUMENT_TYPE_NODE | 10 |
Node.DOCUMENT_FRAGMENT_NODE | 11 |
Node.NOTATION_NODE | 12 |
需要注意的是,在IE中不支持常量
- 1
- 2
- 3
- 1
- 2
- 3
(2)nodeName和nodeValue
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
(3)节点关系
文档中所有节点之间都存在着这样或那样的关系。节点间的各种关系可以用传统的家族关系来描述,相对于把文档树比喻成家谱。
属性 | 说明 |
---|---|
childNodes | 直接子元素;nodeList对象,保存一组有序节点,可通过位置访问 |
parentNode | 文档树中的父节点 |
previousSibling | 前一个兄弟节点 |
nextSibling | 后一个兄弟节点 |
firstChild | 第一个子节点 |
lastChild | 最后一个子节点 |
ownerDocument | 整个文档的文档节点Document |
说明:
- hasChildNodes()在节点包含一个或多个子节点的情况下返回true
- NodeList对象拥有length属性,但并不是Array实例;其是基于DOM结构动态执行查询的结果,因此DOM结构的变化能够自动反应在NodeList对象中。可以通过方括号,也可以使用item()方法访问NodeList中的节点。
示例:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
(4)操作节点
因为关系指针是只读的,所以DOM提供了一些操作节点的方法。
方法 | 说明 |
---|---|
appendChild(newDom) | 向childNode列表的末尾添加一个节点 |
inserBefore(newDom, 参照节点) | 新插入的节点作为参照节点的同胞节点,同时返回该插入节点 |
replaceChild(newDom, 被替换的节点) | 新插入的节点将占据被替换节点的位置 |
removeChild(要移除的节点) | 返回被移除的节点,被移除的节点仍然为稳当所有,只是在文档中没有了位置 |
注意:并不是所有节点都有子节点,如果在不支持子节点的节点上调用了上述方法,将会导致错误发生。
示例:将blog元素移动到content中
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 1
- 2
- 3
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
说明:如果传入到appendChild()中的节点已经是文档的一部分了,那结果就是将该节点从原来的位置转移到新位置。
示例:将blog作为content的第一个子元素,将company作为content的最后一个子元素
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
(5)其他方法
方法 | 说明 |
---|---|
cloneNode(boolean) | true:复制节点及整个子节点树;false:只复制节点本身 |
normalize() | 处理文档树中的文本节点 |
所有节点都有上述方法!
2. Document类型
JavaScript通过Document类型表示文档。在浏览器中,document对象是HTMLDocument的一个实例,表示整个HTML页面。而且,document对象是window对象的一个属性。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
技巧:由于跨域安全限制,来自不同子域的页面无法通过JavaScript通信。而通过将每个页面的document.domain
设置为相同的值,这些页面就可以互相访问对方包含的JavaScript对象了。例如,在www.xxx.com中嵌入了一框架,框架内页面加载自report.xxx.com;两者不能进行访问。可以将两个页面的document.domain
值都设置为xxx.com,就可以互相访问了。
需要注意的是,浏览器对domain有一限制,即如果域名开始时松散的(xxx.com),那么不能将它再设置为紧绷的(www.xxx.com)。
(1)查找元素
方法 | 说明 |
---|---|
getElementById() | 只返回文档中第一次出现的元素;如果不存在带有相应id的元素,则返回null |
getElementsByTagName() | 返回的是包含零或多个元素的HTMLCollection对象 |
getElementsByName() | 返回带有指定name特性的所有元素 |
- 1
- 2
- 3
- 1
- 2
- 3
上述两种方式都可以通过[]代替。在后台,对数值索引会调用item(),对字符串索引会调用namedItem()
。
(2)特殊集合
属性 | 说明 |
---|---|
document.anchors | 包含文档中所有带name特性的元素 |
document.applets | 包含文档中所有的元素 |
document.forms | 包含文档中所有的元素 |
document.images | 包含文档中所有的 |
document.links | 包含文字所有带href特性的元素 |
(3)DOM一致性检测
- 1
- 2
- 1
- 2
存在实现与规范不一致的情况,所以建议除了检测hasFeature()之外,还同时使用能力检测。
(4)文档写入
方法 | 说明 |
---|---|
write() | 原样写入 |
writeln() | 在字符串末尾添加有一个换行符(\n) |
open() | 打开网页输出流 |
close() | 关闭网页输出流 |
示例:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
在文档加载结束后再调用document.write()
,输出的内容将会重写整个页面。
write()、writeln()
可以动态包含外部资源,需注意不能直接包含"</script>"
,因为其会被解释为脚本块的结束。
- 1
- 1
3. Element类型
Element类型用于表现XML和HTML元素。可以通过nodeName或tagName属性获取元素的标签名。
注意:在HTML中,标签名都以大写字母表示;在XML中,标签名始终与源代码中的保持一致。
(1)HTML元素的标准特性
示例:
<div id="myDiv" title="ligang Demo" lang="zh" dir="ltr"
class="bd bf">http://blog.csdn.NET/ligang2585116</div>
属性 | 说明 | 值 |
---|---|---|
div.id | 元素在文档中的唯一标识符 | “myDiv” |
div.title | 附件说明信息,悬停展示 | “ligang Demo” |
div.lang | 元素内容的语言代码 | “zh” |
div.dir | 语言方向:ltr左到右;rtly右到左 | “ltr” |
div.className | CSS类 | “bd bf” |
(2)特性
获取特性:dom.getAttribute("特性名")
如不存在返回null
注意有两类特殊的特性:
- style,返回CSS文本,通过属性访问则返回一个对象;
- onclick等事件处理程序,返回相应代码的字符串。
示例:
- 1
- 2
- 1
- 2
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
设置特性:dom.setAttribute("特性名","值")
(3)attributes属性
attributes属性中包含一个NamedNodeMap
属性 | 说明 |
---|---|
dom.attributes.getNamedItem(name) | 返回nodeName属性等于name的节点 |
dom.attributes.removeNamedItem(name) | 从列表中移除nodeName属性等于name的节点 |
dom.attributes.setNamedItem(attr) | 向列表中添加节点,以节点的nodeName属性为索引 |
dom.attributes.item(pos) | 返回位于数字pos位置处的节点 |
示例:设置属性
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
(5)创建元素
- 1
- 1
创建新元素的同时,也为新元素设置了ownerDocument属性。
示例:创建元素并添加到文档树
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
(6)元素的子节点
元素可以有任意数量的子节点和后代节点。
示例:为了兼容浏览器差异
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
4. Text类型
文本节点由Text类型表示,包含纯文本。纯文本可以包含转义后的HTML字符,但不能包含HTML代码。
(1)创建文本节点:document.createTextNode("文本")
(2)规范化文本节点:在一个包含两个或多个文本节点元素上调用normalize()
,则将会所有文本节点合并成一个节点。
(3)分割文本节点:将一个文本节点分成两个文本节点,按指定的位置分割nodeValue值。
示例:规范化文本节点
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
5. Comment类型
注释在DOM中是通过Comment类型来表示的。
Comment类型与Text类型继承自相同的基类,因此它拥有除了splitText()之外的所有方法,当然也可通过nodeValue或data属性来取得注释的内容。
6. DocumentFragement类型
DocumentFragement类型中没有对应的标记,DOM规定文档片段是一种“轻量级”的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源。可以当做“仓库”使用。
示例:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
7. 其他类型
CDATASection类型、DocumentType类型很少用到,这里不再赘述。
二、DOM操作技术
1. 动态脚本
在元素添加到页面之前,是不会下载外部文件的。(不同于image)
相关内容请查看:事件:事件类型-UI事件
示例:动态加载JavaScript文件
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
示例:动态加载JavaScript代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2. 动态样式
同动态加载脚本类似,添加到页面之后才会加载资源。
示例:动态加载CSSt文件
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
示例:动态加载CSS代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
3. 操作表格
为了方便构建表格,HTML DOM还为<table>
、<tbody>
和 <tr>
元素添加了一些属性:
为<teble>
元素添加的属性和方法:
属性方法 | 说明 |
---|---|
caption | (若有)保存着对<caption> 元素的指针 |
tHead | (若有)保存着对<tHead> 元素的指针 |
tFoot | (若有)保存着对<tFoot> 元素的指针 |
tBodies | 一个所有<tbody> 元素的HTMLCollection |
rows | 一个所有行的HTMLCollection |
createCaption | 创建<caption> 元素,放到表格中,返回引用 |
createTHead() | 创建<thead> 元素,放到表格中,返回引用 |
createTFoot() | 创建<tfoot> 元素,放到表格中,返回引用 |
deleteCaption() | 删除<caption> 元素 |
deleteTHead() | 删除<thead> 元素 |
deleteTFoot() | 删除<tfoot> 元素 |
insertRow(pos) | 向rows集合中的指定位置 插入一行 |
deleteRow(pos) | 删除指定位置的一行 |
<tbody>
元素添加的属性和方法:
属性方法 | 说明 |
---|---|
rows | 一个保存着<tbody> 元素中行的HTMLCollection |
insertRow(pos) | 向rows集合中指定位置插入一行,返回新行的引用 |
deleteRow(pos) | 删除指定位置的行 |
<tr>
元素添加的属性和方法:
属性方法 | 说明 |
---|---|
cells() | 一个保存着<tr> 元素中的单元格的HTMLCollection |
insertCell(pos) | 向cells集合中的指定位置插入一个单元格,返回新单元格引用 |
deleteCell(pos) | 删除指定位置的单元格 |
总结:NodeList、NameNodeMap和HTMLColletction三个集合都是动态的。应尽量减少访问NodeList的次数,因为每次访问NodeList都会运行一次基于上下文档的查询。可以考虑将从NodeList中取得的值缓存起来!