DOM(对象文档模型)是HTML和XML得应用程序接口(API).DOM把整个页面看作有节点层次构成的文档DOM可以通过创建树来表示文档,从而使开发者对文档的内容和结构具有控制力。用DOM API可以轻松地删除、添加和替换节点。通俗的说,DOM表示文档对象模型,是动态操作HTML元素的一系列方法和属性,是HTML程序扩展的接口程序(API)。
把文档表示为树
HTML文档有一个嵌入标记的层级结构,它在DOM中表示对象的一棵树。HTML文档的这个树表示包含了HTML标记和元素(如<body>)的节点,如下面得HTML文档:
<html> <head> <title>DOM文档示例</title> </head> <body> <h1>这是一个文档</h1> <p>这是文档中的一个段落<i>用来演示</i>很好</p> </body> </html> |
这个文档的DOM表示图如下:
|
在以上文档和图中,我们需要了解以下概念:
l 父节点(parent):直接位于一个节点之上的节点是该节点的父节点,比如上边<html>是<head>和<body>的父节点。
l 子节点(children):直接位于一个个点下层的节点是该节点的子节点,比如上边<head>和<body>是<html>的子节点。
l 兄弟节点(sibling):位于同一层次的节点是兄弟节点,比如上边<head>和<body>是兄弟节点。
l 祖先节点(ancestor)和后代节点(descendant):比如上边<html>是所有节点的祖先节点,其他节点都是<html>的后代节点。
节点类型和节点常量
DOM树结构表现为不同种类的Node(节点)对象的一棵树。节点定义了遍历和操作数的属性和方法。Node对象childNodes属性返回节点孩子的一个列表,并且firstChild、lastChild、nextSibling、previousSibling和parentNode属性提供了遍历节点树的一种方法。像appendChild()、removeChild()、replaceChild()和insertBefore()方法能够向一个文档树中添加节点或者从一个文档树中删除节点。稍后我们将看到这些节点的具体应用。
节点类型
l Document:最顶层节点,所有其他节点都附属于它。
l DomcumentFragment:可以像Document一样来保存其他节点。
l Element:表示起始标签和结束标签之间的内容,如<font></font>或者<br/>,这是唯一可以同时包含特性和子节点的节点类型。
l Attr:特性节点,这个节点不能包含子节点。如:bgcolor=”red”。
l Text:在起始标签和结束标签中包含的普通文本内容,这个节点不能包含子节点。
节点类型和节点常量的对应关系
每个Node对象都有一个nodeType属性,它指定了节点是什么类型,并且nodeType有一个常量和其值进行对应,下表是常用节点和常量的对应关系。
节点类型 | 节点类型常量 | 节点类型常量对应数值 |
Element | Node.ELEMENT_NODE | 1 |
Attr | Node.ATTRIBUTE_NODE | 2 |
Text | Node.TEXT_NODE | 3 |
Comment(注释) | Node.COMMENT_NODE | 8 |
Document | Node.DOCUMENT_NODE | 9 |
DocumentFragment | Node.DOCUMENT_FRAGMENT_NODE | 11 |
DOM树根部的Node是一个Document对象,该对象的documentElement属性引用了一个Element对象,它代表文档的根元素。对于HTML文档,这是<html>标记,Document节点还可以有其他孩子结点,如Comment(注释)节点。在HTML文档中<body>元素有时候比<html>元素更有用,为了方便起见,可以使用document.body来引用这个元素。一个DOM中只有一个Document对象,DOM的大部分节点是表示标记的Element对象和表示文本的Text对象。
节点的方法和属性
Node定义了一些所有节点类型都包含的特性和方法,具体见下表:
特性/方法 | 类型/返回类型 | 说明 |
nodeName | String | 节点的名字,根据节点的类型而定义 |
nodeValue | String | 节点的值,根据节点的类型而定义 |
nodeType | Number | 节点类型的常量值之一 |
ownerDocument | Document | 指向这个节点所属的文档 |
firstChild | Node | 指向在childNodes列表中的第一个节点 |
previousSibling | Node | 指向前一个兄弟节点,如果这个节点就是第一个兄弟节点则返回null |
lastChild | Node | 指向在childNodes列表中的最后一个节点 |
childNodes | NodeList | 所有子节点列表 |
nextSibling | Node | 指向最后一个兄弟节点,如果这个节点就是最后一个兄弟节点则返回null |
hasChildNodes() | Boolean | 当childNodes包含一个或多个子节点是返回true |
Attibutes | NamedNodeMap | 一个元素的Attr对象,仅用于Element节点 |
appengdChild(node) | Node | 将node添加到childNodes的末尾 |
removeChild(node) | Node | 从childNodes中删除node |
replaceChild (newnode,oldnode) | Node | 将childNodes中的oldnode替换成newnode |
insertBefore (newnode,refnode) | Node | 在childNodes中的refnode前插入newnode |
HTML语言的DOM
W3C开发了针对XHTML和HTML的DOM。这个DOM定义了一个HTMLDocument和一个HTMLElement作为实现的基础。每个HTML元素通过自己的HTMLElement类型表示,如HTMLDivElement表示</div>。
对DOM的支持
每种浏览器对DOM的支持程度都不同,一般来说,Mozilla对DOM的支持最好IE最差,因此在使用DOM的时候需要注意,可能不会出现预期的效果。
使用DOM
l 检测节点类型、名称、兄弟节点
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <script type="text/javascript"> function init() { var strInfo=""; var objRoot=document.documentElement;//获取文档节点 strInfo+="文档节点类型为:"+objRoot.nodeType+"\t节点名称为:"+objRoot.nodeName+"</br>"; //获取文档节点的第一个子节点 var firstNode=objRoot.firstChild;//objRoot.childNodes[0] //获取文档节点第一个子节点的子节点,首先判断该节点是否有子节点 if(firstNode.hasChildNodes()) { var firstChildList=firstNode.childNodes; //将此信息追加到字符串上 strInfo+="文档节点的第一个子节点类型为:"+firstNode.nodeType+"\t节点名称为:"+firstNode.nodeName+"<br/>该节点的子节点为:<br/>"; for(var node=0;node<firstChildList.length;node++) { strInfo+="<font color='red'>节点名称为:"+firstChildList[node].nodeName+"\t节点类型为:"+firstChildList[node].nodeType+"<br/></font>";
} } //获取文档节点第一个子节点的下一个兄弟节点 var nextNode=firstNode.nextSibling; strInfo+="下个兄弟节点名称为:"+nextNode.nodeName+"<br/>"; //获取nextNode的上一个兄弟节点和父节点 var preNode=nextNode.previousSibling; //获取nextNode的父节点 var parent=nextNode.parentNode; strInfo+="该节点的上个兄弟节点名称为:"+preNode.nodeName+"\t父节点为:"+parent.nodeName; document.write(strInfo);
} </script> <title>dom检测</title> </head>
<body> <p align="center">这是一段文字</p> <p id="secondNode">这是第二段文字</p> <p>这是第三段文字</p> <input type="button" value="查看文档信息" οnclick="init()"/> </body> </html> |
l 处理属性
在文档中,只有元素节点(Element)才具有特性(Attribute)。元素节点(Element)的attribues属性其实是NamedNodeMap,它提供一些方法用于处理其内容。方法有:
1. getNamedItem(name):返回nodeName属性值等于name的节点;
2. removeNamedItem(name):删除modeName属性值等于name的节点。
3. setNamedItem(node):将node添加到列表中,按其nodeName属性进行索引。
4. item(pos):和NodeList一样,返回在位置pos的节点。
注意:以上方法均返回一个Attr节点,不是特性值。NamedNodeMap对象也有一个length属性来统计它包含的节点数量。当NamedNodeMap用于表示特性时,其中每个节点都是Attr节点,它的nodeName属性是特性名称,nodeValue属性为特性的值。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>DOM测试</title> <script type="text/javascript"> function check() { //获取body节点 var objBody=document.body; //判断body中有没有元素 if(objBody.hasChildNodes()) { //循环取出每一个元素 for(var nd=0;nd<objBody.childNodes.length;nd++) { var node=objBody.childNodes[nd]; //判断每一个节点的类型和名称,如果是段落节点则做相关处理 if(node.nodeName=="P" && node.nodeType==1) { //判断段落节点是否有属性 //if(node.hasAttributes()) //{ //IE7不支持此方法 //} //获取指定属性的值 //alert(node.attributes.item[0].nodeValue);IE7不支持此属性 //alert(node.attributes.getNamedItem("id").nodeValue); // nodeValue表示属性值在IE7中通过测试 //alert(node.getAttribute("id"));//在IE7中通过测试 //alert(node.getAttribute("align")); //----------------------------------------------------- //修改制定属性的值 //node.attributes.getNamedItem("align").nodeValue="left"; //node.setAttribute("align","right"); //----------------------------------------------------- //删除指定的属性 node.removeAttribute("align");
} } } } </script> </head>
<body> <h1>这是一个文档</h1> <p id="p1" align="center">这是文档中的一个段落<i>用来演示</i>很好</p> <input type="button" value="检测" οnclick="check()" /> </body> </html> |
l 获取指定节点的文本内容
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>DOM测试</title> <script type="text/javascript"> function check() { var pArray=document.getElementsByTagName("p"); for(var i=0;i<pArray.length;i++) {
if(pArray[i].attributes.getNamedItem("id").nodeValue=="p2") { alert(pArray[i].innerText); } } } </script> </head>
<body> <h1>这是一个文档</h1> <p id="p1" align="center">这是文档中的一个段落<i>用来演示</i>很好</p> <p id="p2" align="center">这是文档中的一个段落<i>用来演示</i>很好</p> <p id="p3" align="center">这是文档中的一个段落<i>用来演示</i>很好</p> <p id="p4" align="center">这是文档中的一个段落<i>用来演示</i>很好</p> <input type="button" value="检测" οnclick="check()" /> </body> </html> |
l 使用DOM动态创建HTML节点
案例1:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>DOM创建元素</title> <script type="text/javascript"> function build() { //创建一个段落元素 var objP=document.createElement("p"); //创建一个文本(节点) var objText=document.createTextNode("这是动态创建的文字"); //把创建好的文本(节点)添加到段落上 objP.appendChild(objText); //document.body.appendChild(objP); var objBody=document.body; var bt=document.getElementById("bt"); //把段落追加到body元素中 //objBody.insertBefore(objP,bt); //把段落插入到指定元素前 objBody.replaceChild(objP,bt);
} </script> |
案例2:动态创建元素,设置元素样式及调用事件处理函数
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>动态创建元素</title> <style type="text/css"> .inputCss { width:100px; height:25px; border:1px #333333 dotted;
} </style> <script type="text/javascript"> //创建节点 function build() { //创建input元素 var objInput=document.createElement("input"); //设置input元素的属性 objInput.setAttribute("type","text"); objInput.setAttribute("id","txtUserName"); //指定input元素的样式class名,因为class在js中是关键字,所以用className代替 objInput.className="inputCss"; document.body.appendChild(objInput); var objButton=document.createElement("input"); objButton.setAttribute("type","button");//===><input type="button"> //objButton.type="button"; objButton.setAttribute("id","btSure"); //objButton.id="btSure"; objButton.setAttribute("value","确定"); //objButton.value="确定"; //设置按钮的点击事件并调用函数 objButton.οnclick=getData; document.body.appendChild(objButton); } //事件处理函数,此为匿名函数 var getData=function() { var uName=document.getElementById("txtUserName"); if(uName.value=="") { alert("用户名不能为空"); } else { alert(uName.value); } } </script> </head>
<body> <input type="button" id="bt" value="创建" οnclick="build()" /> </body> </html> |
l 使用DOM动态创建表格
在创建表格时需要注意,必须使用Tbody元素,其他相关节点附加在此节点上,然后附加到table元素上。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>DOM动态创建表格</title> <script type="text/javascript"> function build() { var objTb=document.createElement("table"); objTb.setAttribute("border","1"); objTb.setAttribute("width","800"); objTb.setAttribute("height","100"); objTb.style.borderCollapse="collapse";
var objTbody=document.createElement("tbody"); for(var i=1;i<4;i++) { var objTr=document.createElement("tr"); for(var j=1;j<3;j++) { var objTd=document.createElement("td"); var objText=document.createTextNode("行"+i+"列"+j); objTd.appendChild(objText); objTr.appendChild(objTd); } objTbody.appendChild(objTr); }
objTb.appendChild(objTbody); document.body.appendChild(objTb);
} </script> </head>
<body> <input type="button" value="创建" οnclick="build()" /> </body> </html> |