一、概述
DOM(Document Object Model,文档对象模型)是针对HTML和XML文档的一个API(应用程序编程接口),是定义访问和处理HTML文档的标准方法。
DOM将HTML文档呈现为带有元素、属性和文本的树结构(节点树),允许开发人员添加、移除和修改页面的某一部分。
举个例子,看如下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Shopping list</title>
</head>
<body>
<h1>What to buy</h1>
<p title="a gentle reminder">
Don't forget to buy this stuff.
</p>
<ul id="purchase">
<li>A tin of beans</li>
<li class="sale">Cheese</li>
<li class="sale important">Milk</li>
</ul>
</body>
</html>
将上述HTML代码分解为DOM节点层次图,如下:
可以这么理解,HTML文档是由节点构成的集合。
二、节点类型
(一)Node类型
- JavaScript中所有节点类型都继承自Node类型。
- Node接口是作为Node类型实现的。
- 除了IE之外,在其他浏览器中都可以访问到这个类型。
- 不是每种节点都有子节点。
1、节点属性
1)nodeType:用于表明节点的类型,返回一个整数,这个数值代表着给定节点的类型。
节点类型 | 描述 |
---|---|
Node.ELEMENT_NODE(1) | 元素节点 |
Node.ATTRIBUTE_NODE(2) | 属性节点 |
Node.TEXT_NODE(3) | 文本节点 |
Node.CDATA__SECTIONNODE(4) | 文档的CDATA部分(不会由解析器解析的文本) |
Node.ENTITY_PEFERENCE_NODE(5) | 实体引用 |
Node.ENTITY_NODE(6) | 实体 |
Node.PROCESSING_INSTRUCTION_NODE(7) | 处理指令 |
Node.COMMENT_NODE(8) | 注释 |
Node.DOCUMENT_NODE(9) | 整个文档(DOM树的根节点) |
Node.DOCUMENT_TYPE_NODE(10) | 为文档定义的实体提供接口 |
Node.DOCUMENT_FRAGMENT_NODE(11) | 轻量级的Document对象,能够容量文档的某个部分 |
Node.NOTATION_NODE(12) | DTD中声明的符号 |
为了确保浏览器兼容,最好将nodeType属性与数字值进行比较。
//适用于所有浏览器
if (someNode.nodeType == 1){
alert("Node is an element.");
}
2)nodeName:节点的名称。
- 如果是元素节点,返回这个元素的名称。
- 如果是属性节点,返回这个属性的名称。
- 如果是文本节点,返回一个内容为#text的字符串。
3)nodeValue:节点的值。
- 如果给定节点是一个属性节点,返回值是这个属性的值。
- 如果给定节点是一个文本节点,返回值是这个文本节点内容。
- 如果给定节点是一个元素节点,返回值是null。
2、节点关系
节点之间的关系可以用传统的家族来描述,换句话说,把文档树比喻成家谱。
1)childNodes:获取指定节点的所有子节点集合。
每个节点都有一个childNodes属性,其中保存着一个NodeList对象。
NodeList对象用于保存一组有序的节点,可以通过位置来访问这些节点,是基于DOM结构动态执行查询的结果。
这个对象不是Array的实例,但也有length属性。length属性表示的是访问NodeList的那一刻,其中包含的节点数量。
访问保存在NodeList中的节点的方式:
- 方括号
- item()
var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;
还可以将NodeList对象转换为数组。
function convertToArray(nodes){
var array = null;
try {
array = Array.prototype.slice.call(someNode.childNodes,0);//针对非IE浏览器
}
catch (ex) {
//手动枚举所有成员
array = new Array();
for (var i=0, len=nodes.length; i<len; i++){
array.push(nodes[i]);
}
}
return array;
}
2)parentNode:指向文档树中的父节点。该属性返回的节点永远是一个元素节点,因为只有元素节点才有可能包含子节点。
3)同胞节点:包含在NodeList列表中的每个节点相互之间都是同胞节点。
- previousSibling:返回一个给定节点的上一个兄弟节点。其中,列表中的第一个节点的previousSibling属性的值为null。
- nextSibling:返回一个给定节点的下一个兄弟节点。其中,列表中的最后一个节点的nextSibling属性的值为null。
4)子节点
- firstChild:获取指定childNodes列表中的第一个子节点。
- lastChild:获取指定childNodes列表中的最后一个节点。
5)ownerDocument属性:指向表示整个文档的文档节点。
这种关系表示的是任何节点都属于它所在的文档,任何节点都不能同时存在于两个或更多个文档中。
通过这个属性,我们可以不必在节点层次中通过层层回溯达到顶端,而是可以直接访问文档节点。
3、操作节点的方法
- appendChild():用于向childNodes列表的末尾添加一个节点。
- 接收一个参数,即要添加的节点。
- 更新节点后返回新增的节点。
- insertBefore():可以将节点放在childNodes列表中某个特定的位置。
- 接收两个参数:要插入的节点和作为参照的节点。
- 返回要插入的节点。
- replaceChild():将要插入的节点替换要替换的节点。
- 接收两个参数:要插入的节点和要替换的节点。
- 返回要替换的节点。
- removeChild():移除指定节点。
- 接收一个参数,即要移除的节点。
- 返回被移除的节点。
//添加后成为最后一个子节点
var returnedNode = someNode.appendChild(newNode);
//插入后成为最后一个子节点
returnedNode = someNode.insertBefore(newNode,null);
//插入后成为第一个子节点
returnedNode = someNode.insertBefore(newNode,someNode.firstChild);
//替换第一个子节点
returnedNode = someNode.replaceChild(newNode,someNode.firstChild);
//移除第一个子节点
returnedNode = someNode.removeChild(someNode.firstChild);
4、其他方法
- cloneNode():复制节点。
- 接收一个布尔值参数。
- 参数为true时,执行深复制,即复制节点及其整个子节点树。
- 参数为false时,执行浅复制,即只复制节点本身。
- 返回的节点副本属于文档所有,但并没有为它指定父节点。
- 不会复制添加到DOM节点中的JavaScript属性。
- 接收一个布尔值参数。
- normalize():处理文档树中的文本节点。
- 如果找到空文本节点,则删除它。
- 如果找到相邻的文本节点,则将它们合并为一个文本节点。
(二)Document类型
- 表示文档。
- 在浏览器中,document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面。
- document对象是window对象的一个属性,可以作为全局对象来访问。
1、文档的子节点
可以是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Comment。
两个内置的访问其子节点的方式:
- documentElement属性,该属性始终指向HTML页面的
<html>
元素。 - 通过childNodes列表访问文档元素。
2、文档信息
- title属性:包含
<title>
元素中的文本——显示在浏览器窗口的标题栏或标签页上。 - URL属性:包含页面完整的URL,即地址栏中显示的URL。
- domain属性:只包含页面的域名。
- referrer属性:保存着链接到当前页面的那个页面的URL。如果没有来源页面,则可能包含空字符串。
3、查找元素
- document.getElementById()
- 接收一个参数,即要取得的元素的ID。
- 如果找到,返回该元素,否则返回null。
- getElementsByTagName()
- 接收一个参数,即要取得元素的标签名。
- 返回包含零或多个元素的NodeList。
- 要想取得文档中的所有元素,则传入”*”。
- getElementsByName()
- HTMLDocument类型特有的方法。
- 返回带有给定name特性的所有元素。
4、特殊集合(HTMLCollection对象)
- document.anchors:包含文档中所有带name特性的
<a>
元素。 - document.applets:包含文档中所有的
<applet>
元素。不推荐使用。 - document.forms:包含文档中所有的
<form>
元素。 - document.images:包含文档中所有的
<img>
元素。 - document.links:包含文档中所有带href特性的
<a>
元素。
5、DOM一致性检测
- document.implementation属性是为此提供相应信息和功能的对象,与浏览器对DOM的实现直接对应。
- hasFeature():接收两个参数,即要检测的DOM功能的名称及版本号。如果支持,返回true。
6、文档写入
1)write()和writeln()
- 接收一个字符串参数,即要写入到输出流中的文本。
- write()原样输入,而writeln()在字符串末尾添加一个换行符。
- 在页面加载的过程中,可以向页面动态地加入内容。
<body>
<p>The current date and time is:
<script type="text/javascript">
document.write("<strong>" + (new Date()).toString() + "</strong>");
</script>
</p>
</body>
- 可以动态地包含外部资源。
<body>
<p>Because the string "</script>" is included with <code>document.write()</code>,
the script tag is closed before reaching its natural end. That means you'll see some extra
text here:</p>
<script type="text/javascript">
document.write("<script type=\"text\javascript\" src=\"file.js\">" +
"</script>");
</script>
</body>
- 在文档结束后调用,输出的内容将会重写整个页面。
<body>
<p>This is some content that you won't get to see because it will be overwritten.</p>
<script type="text/javascript">
window.onload = function(){
document.write("Hello world!");
};
</script>
</body>
2)open():打开网页的输出流。
3)close():关闭网页的输入流。