文档对象模型(document object model,DOM)是W3C制定的一套技术规范,用来描述JavaScript脚本与HTML文档进行交互的Web标准。DOM规定了一系列标准接口,允许开发人员通过标准方式访问文档结构、操作网页内容、控制样式和行为等。
节点(node)是DOM最基本的单元,并派生出不同类型的节点,它们共同构成文档结构模型。在网页中所有对象和内容都被称为节点,如文档、元素、文本、属性、注释等。
根据DOM规范,整个文档是一个文档节点,每个标签是一个元素节点,包含的文本是文本节点,标签的属性是一个属性节点,注释属于注释节点等。DOM节点类型说明如下表所示:
使用nodeType属性可以判断一个节点的类型,取值说明如下表所示:
使用nodeName和nodeValue属性可以读取节点的名称和值,属性取值说明如下表所示:
【示例】不同类型的节点,nodeName和nodeValue属性取值是不同的。元素的nodeName属性返回值是标签名,而元素的nodeValue属性返回值为null。因此在读取属性值之前,应该先检测类型:
var node = document.getElementsByTagName("body")[0];
if (node.nodeType==1)
var value = node.nodeName;
console.log(value);
nodeName属性在处理标签时比较实用,而nodeValue属性在处理文本信息时比较实用。
DOM为Node类型定义如下属性,以方便JavaScript访问节点:
【示例】针对下面文档结构:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body><span class="red">body</span>元素</body></html>
可以使用下面方法访问body元素:
var b = document.documentElement.lastChild;
var b = document.documentElement.firstChild.nextSibling.nextSibling;
通过下面方法可以访问span包含的文本:
var text = document.documentElement.lastChild.firstChild.firstChild.nodeValue;
操作节点的基本方法如下表所示:
提示:appendChild()、insertBefore()、removeChild()、replaceChild() 4种方法用于对子节点进行操作。使用这4种方法之前,可以使用parentNode属性先获取父节点。另外,并不是所有类型的节点都有子节点,如果在不支持子节点的节点上调用这些方法将会导致错误发生。
【示例】为列表框绑定一个click事件处理程序,通过深度克隆,新的列表框没有添加JavaScript事件,仅克隆HTML类样式和style属性:
<h1>DOM</h1>
<p>DOM是<cite>Document Object Model</cite>首字母简写,中文翻译为<b>文档对象模型</b>,是<i>W3C</i>组织推荐
的处理可扩展标识语言的标准编程接口。</p>
<ul>
<li class="red">D表示文档,HTML文档结构。</li>
<li title="列表项目2">O表示对象,文档结构的JavaScript脚本化映射。</li>
<li style="color:red;">M表示模型,脚本与结构交互的方法和行为。</li>
</ul>
<script>
var ul = document.getElementsByTagName("ul")[0]; //获取列表元素
ul.onclick = function(){ //绑定事件处理程序
this.style.border= "solid blue 1px";
}
var ul1 = ul.cloneNode(true); //深度克隆
document.body.appendChild(ul1); //添加到文档树中body元素下
</script>
文档节点代表整个文档,使用document可以访问文档节点,它是文档内其他节点的访问入口,提供了操作其他节点的方法。文档节点是唯一的,也是只读的,主要特征:nodeType等于9、nodeName等于"#document"、nodeValue等于null、parentNode等于null、ownerDocument等于null。
在不同环境中,获取文档节点的方法也不同,具体说明如下:
文档子节点包括以下元素:
。
。
。
。访问方法如下:
文档中存在很多特殊元素,使用下面的方法可以获取,如果获取不到,将返回null。
document包含一组集合对象,使用它们可以快速地访问文档内元素,简单说明如下:
标签。
标签。document包含很多信息,简单说明如下:
document对象包含多个访问文档内元素的方法,简单说明如下:
【示例】先获取所有图片,再通过namedItem(“news”);找到name为news的图片:
<img src="1.gif" />
<img src="2.gif" name="news" />
<script>
var images = document.getElementsByTagName("img");
var news = images.namedItem("news");
</script>
也可以使用下面用法获取页面中所有的元素,其中参数*表示所有元素:
var allElements = document.getElementsByTagName("*");
元素节点的主要特征:nodeType等于1、nodeName等于标签名称、nodeValue等于null。元素节点包含5个公共属性,即id(标识符)、title(提示标签)、lang(语言编码)、dir(语言方向)、className(CSS类样式),这些属性可读可写。
使用getElementById()方法可以准确地获取文档中指定的元素,用法如下:
document.getElementById(ID)
参数ID表示文档中对应元素的id属性值。如果文档中不存在指定元素,则返回值为null,该方法只适用于document对象。
【示例1】使用getElementById()方法获取 使用getElementByTagName()方法可以获取指定标签名称的所有元素,用法如下: 参数tagName表示指定名称的标签,该方法返回值为一个节点集合,使用length属性可以获取集合中包含元素的个数,利用下标可以访问其中某个元素对象。 【示例2】使用for循环获取每个p元素,并设置p元素的class属性为red: 使用parentNode、nextSibling、previousSibling、firstChild和lastChild属性可以遍历文档树中任意类型节点,包括空字符(文本节点)。HTML5新添加5个属性专门访问元素节点。 浏览器支持:IE 9+、Firefox 3.5+、Safari 4+、Chrome和Opera 10+。 使用document对象的createElement()方法能够根据参数指定的标签名称创建一个新的元素,并返回新建元素的引用。用法如下: 其中,element表示新建元素的引用,createElement()是document对象的一个方法,该方法只有一个参数,用来指定创建元素的标签名称。 【示例1】在当前文档中创建一个段落标记p,存储到变量p中。由于该变量表示一个元素节点,所以它的nodeType属性值等于1,而nodeName属性值等于p: 使用createElement()方法创建的新元素不会被自动添加到文档里。如果要把这个元素添加到文档里,还需要使用appendChild()、insertBefore()或replaceChild()方法实现。 【示例2】演示把新创建的p元素增加到body元素下。当元素被添加到文档树中,就会立即显示出来: cloneNode()方法可以创建一个节点的副本。 【示例】演示复制一个元素及其所有子节点。当复制其中创建的标题1节点之后,该节点所包含的子节点及文本节点都将复制过来,然后增加到body元素的尾部: 注意:由于复制的节点会包含原节点的所有特性,如果原节点中包含id属性,就会出现id属性值重叠的情况。一般情况下,在同一个文档中,不同元素的id属性值应该不同。为了避免潜在冲突,应修改其中某个节点的id属性值。 在文档中插入节点主要包括两种方法: appendChild()方法可向当前节点的子节点列表的末尾添加新的子节点,用法如下: 参数newchild表示新添加的节点对象,并返回新增的节点。 【示例】展示把段落文本增加到文档中指定的div元素中,使它成为当前节点的最后一个子节点: 如果文档树中已经存在参数节点,则将从文档树中删除,然后重新插入新的位置。如果添加节点是DocumentFragment节点,则不会直接插入,而是把它的子节点插入当前节点的末尾。 使用insertBefore()方法可以在已有的子节点前插入一个新的子节点,用法如下: 其中,参数newchild表示新插入的节点,refchild表示插入新节点后的节点,用于指定插入节点的后面相邻的位置。插入成功后,该方法将返回新插入的子节点。 提示:insertBefore ()方法与appendChild()方法一样,可以把指定元素及其所包含的所有子节点都一起插入指定位置中。同时会先删除移动的元素,然后再重新插入新的位置。 removeChild()方法可以从子节点列表中删除某个节点,用法如下: 其中,参数node为要删除的节点。如果删除成功,则返回被删除节点;如果删除失败,则返回null。 当使用removeChild()方法删除节点时,该节点所包含的所有子节点将同时被删除。 【示例】单击按钮时将删除红盒子中的一级标题: replaceChild()方法可以将某个子节点替换为另一个子节点,用法如下: 其中,参数new_node为指定新的节点,old_node为被替换的节点。如果替换成功,则返回被替换的节点;如果替换失败,则返回null。 【示例】以上节示例为基础,重写脚本,新建一个二级标题元素,并替换红色盒子中的一级标题元素: 演示发现,当使用新创建的二级标题替换一级标题之后,则原来的一级标题所包含的标题文本已经不存在。这说明,替换节点的操作不是替换元素名称,而是替换其包含的所有子节点,以及其包含的所有内容。 文本节点表示元素和属性的文本内容,包含纯文本内容、转义字符,但不包含HTML代码。文本节点不包含子节点。其主要特征:nodeType等于3、nodeName等于"#text"、nodeValue等于包含的文本。 使用document对象的createTextNode()方法可以创建文本节点,用法如下: 参数data表示字符串。 【示例】创建一个新div元素,并为它设置class值为red,然后添加到文档中: 注意:由于DOM操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点的情况。为了避免这种情况,一般应该在父元素上调用normalize()方法,删除空文本节点,合并相邻文本节点。 使用nodeValue或data属性可以访问文本节点包含的文本。使用length属性可以获取包含文本的长度,利用该属性可以遍历文本节点中的每个字符。 使用元素的innerHTML属性可以返回调用元素包含的所有子节点对应的HTML标记字符串。最初它是IE的私有属性,HTML5规范了innerHTML的使用,并得到所有浏览器的支持。 【示例】使用innerHTML属性读取div元素包含的HTML字符串: 使用innerHTML属性可以根据传入的HTML字符串,创建新的DOM片段,然后用DOM片段完全替换调用元素原有的所有子节点。设置innerHTML属性值之后,可以像访问文档中的其他节点一样访问新创建的节点。 【示例】创建一个1000行的表格。先构造一个HTML字符串,然后更新DOM的innerHTML属性: <div id="box">盒子</div>
<script>
var box = document.getElementById("box"); //获取指定盒子的引用
var info = "nodeName:" + box.nodeName; //获取该节点的名称
info += "\rnodeType:" + box.nodeType; //获取该节点的类型
info += "\rparentNode:" + box.parentNode.nodeName; //获取该节点的父节点名称
info += "\rchildNodes:" + box.childNodes[0].nodeName; //获取该节点的子节点名称
console.log(info); //显示提示信息
</script>
2.getElementByTagName()方法
document.getElementsByTagName(tagName)
var p = document.getElementsByTagName("p"); //获取p元素的所有引用
for(var i=0;i<p.length;i++){ //遍历p数据集合
p[i].setAttribute("class","red"); //为每个p元素定义red类样式
}
3.2、遍历元素
3.3、创建元素
var element = document.createElement("tagName");
var p = document.createElement("p"); //创建段落元素
var info = "nodeName:" + p.nodeName; //获取元素名称
info += ",nodeType:" + p.nodeType; //获取元素类型,如果为1则表示元素节点
console.log(info);
var p = document.createElement("p"); //创建段落元素
document.body.appendChild(p); //增加段落元素到body元素下
3.4、复制元素
var p = document.createElement("p"); //创建一个p元素
var h1 = document.createElement("h1"); //创建一个h1元素
var txt = document.createTextNode("Hello World"); //创建一个文本节点,文本内容为“Hello World”
p.appendChild(txt); //把文本节点增加到段落中
h1.appendChild(p); //把段落元素增加到标题元素中
document.body.appendChild(h1); //把标题元素增加到body元素中
var new_h1 = h1.cloneNode(true); //复制标题元素及其所有子节点
document.body.appendChild(new_h1); //把复制的新标题元素增加到文档中
3.5、插入元素
1.appendChild()方法
appendChild(newchild)
<div id="box"></div>
<script>
var p = document.createElement("p"); //创建段落节点
var txt = document.createTextNode("盒模型"); //创建文本节点,文本内容为“盒模型”
p.appendChild(txt); //把文本节点增加到段落节点中
document.getElementById("box").appendChild(p); //获取box元素,把段落节点增加进来
</script>
2.insertBefore()方法
insertBefore(newchild,refchild)
3.6、删除元素
nodeObject.removeChild(node)
<div id="red">
<h1>红盒子</h1>
</div>
<div id="blue">蓝盒子</div>
<button id="ok">移动</button>
<script>
var ok = document.getElementById("ok"); //获取按钮元素的引用
ok.onclick = function(){ //为按钮注册一个鼠标单击事件处理函数
var red = document.getElementById("red"); //获取红色盒子的引用
var h1 = document.getElementsByTagName("h1")[0]; //获取标题元素的引用
red.removeChild(h1); //移出红盒子包含的标题元素
}
</script>
3.7、替换元素
nodeObject.replaceChild(new_node,old_node)
var ok = document.getElementById("ok"); //获取按钮元素的引用
ok.onclick = function(){ //为按钮注册一个鼠标单击事件处理函数
var red = document.getElementById("red"); //获取红色盒子的引用
var h1 = document.getElementsByTagName("h1")[0]; //获取一级标题的引用
var h2 = document.createElement("h2"); //创建二级标题元素,并引用
red.replaceChild(h2,h1); //把一级标题替换为二级标题
}
4、文本
4.1、创建文本
document.createTextNode(data)
var element = document.createElement("div");
element.className = "red";
document.body.appendChild(element);
4.2、访问文本
4.3、读取HTML字符串
<div id="div1">
<style type="text/css">p { color:red;}</style>
<p><span>div</span>元素</p>
</div>
<script>
var div = document.getElementById("div1");
var s = div.innerHTML;
console.log(s);
</script>
4.4、插入HTML字符串
<script>
function tableInnerHTML() {
var i, h = ['