文档对象模型(DOM) childnodes[n].nodeValue 来获取节点值 childnodes[n].nodeType 来获取节点类型 childnodes[n].nodeName 来获取节点名字
这个是不是跟XML的结构有点相似呢。不同的是,HTML文档的树形主要包含表示元素、标记的节点和表示文本串的节点。 7.4.2、HTML文档的节点DOM下,HTML文档各个节点被视为各种类型的Node对象。每个Node对象都有自己的属性和方法,利用这些属性和方法可以遍历整个文档树。由于HTML文档的复杂性,DOM定义了nodeType来表示节点的类型。这里列出Node常用的几种节点类型:
DOM树的根节点是个Document对象,该对象的documentElement属性引用表示文档根元素的Element对象(对于HTML文档,这个就是<html>标记)。Javascript操作HTML文档的时候,document即指向整个文档,<body>、<table>等节点类型即为Element。Comment类型的节点则是指文档的注释。具体节点类型的含义,请参考《Javascript权威指南》,在此不赘述。 Document定义的方法大多数是生产型方法,主要用于创建可以插入文档中的各种类型的节点。常用的Document方法有:
对于Element节点,可以通过调用getAttribute()、setAttribute()、removeAttribute()方法来查询、设置或者删除一个Element节点的性质,比如<table>标记的border属性。下面列出Element常用的属性:
Element常用的方法:
Attr对象代表文档元素的属性,有name、value等属性,可以通过Node接口的attributes属性或者调用Element接口的getAttributeNode()方法来获取。不过,在大多数情况下,使用Element元素属性的最简单方法是getAttribute()和setAttribute()两个方法,而不是Attr对象。 7.4.3、使用DOM操作HTML文档Node对象定义了一系列属性和方法,来方便遍历整个文档。用parentNode属性和childNodes[]数组可以在文档树中上下移动;通过遍历childNodes[]数组或者使用firstChild和nextSibling属性进行循环操作,也可以使用lastChild和previousSibling进行逆向循环操作,也可以枚举指定节点的子节点。而调用appendChild()、insertBefore()、removeChild()、replaceChild()方法可以改变一个节点的子节点从而改变文档树。 需要指出的是,childNodes[]的值实际上是一个NodeList对象。因此,可以通过遍历childNodes[]数组的每个元素,来枚举一个给定节点的所有子节点;通过递归,可以枚举树中的所有节点。下表列出了Node对象的一些常用属性和方法: Node对象常用属性:
Node对象常用方法:
接下来,让我们使用上述的DOM应用编程接口,来试着操作HTML文档。 A、遍历文档的节点 DOM把一个HTML文档视为树,因此,遍历整个树是应该是家常便饭。跟之前说过的一样,这里我们提供两个遍历树的例子。通过它,我们能够学会如何使用childNodes[]和firstChile、lastChild、nextSibling、previousSibling遍历整棵树。 例子1-- sample3_1.htm: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>无标题文档</title> <script language="javascript"> var elementName = ""; //全局变量,保存Element标记名,使用完毕要清空 function countTotalElement(node) { //参数node是一个Node对象 var total = 0; if(node.nodeType == 1) { //检查node是否为Element对象 total++; //如果是,计数器加1 elementName = elementName + node.tagName + "/r/n"; //保存标记名 } var childrens = node.childNodes; //获取node的全部子节点 for(var i=0;i<childrens.length;i++) { total += countTotalElement(childrens[i]); //在每个子节点上进行递归操作 } return total; } </script> </head> <body> <a href="javascript:void(0)" onClick="alert('标记总数:' + countTotalElement(document) + '/r/n 例子2 – sample3_2.htm: function countTotalElement(node) { //参数node是一个Node对象 var total = 0; if(node.nodeType == 1) { //检查node是否为Element对象 total++; //如果是,计数器加1 elementName = elementName + node.tagName + "/r/n"; //保存标记名 } var childrens = node.childNodes; //获取node的全部子节点 for(var m=node.firstChild; m!=null;m=m.nextSibling) { total += countTotalElement(m); //在每个子节点上进行递归操作 } return total; } B、搜索文档中特定的元素 document.getElementsByTagName()返回文档中具有指定标记名的全部Element节点数组(也是NodeList类型)。Element出现在数组中的顺序就是他们在文档中出现的顺序。传递给getElementsByTagName()的参数忽略大小写。比如,想定位到第一个<table>标记,可以这样写:document.getElementsByTagName(“table”)[0]。例外的,可以使用document.body定位到<body>标记,因为它是唯一的。 getElementsByTagName()返回的数组取决于文档。一旦文档改变,返回结果也立即改变。相比,getElementById()则比较灵活,可以随时定位到目标,只是要实现给目标元素一个唯一的id属性值。这个我们在《AJAX开发简略》的“级联菜单”例子中已经使用过了。 Element对象也支持getElementsByTagName()和getElementById()。不同的是,搜索领域只针对调用者的子节点。 C、修改文档内容 例子3 -- sample4_1.htm: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>无标题文档</title> <script language="javascript"> function reverseNode(node) { // 颠倒节点node的顺序 var kids = node.childNodes; //获取子节点列表 var kidsNum = kids.length; //统计子节点总数 for(var i=kidsNum-1;i>=0;i--) { //逆向遍历子节点列表 var c = node.removeChild(kids[i]); //删除指定子节点,保存在c中 node.appendChild(c); //将c放在新位置上 } } </script> </head> <body> <p>第一行</p> <p>第二行</p> <p>第三行</p> <p><input type="button" name="reverseGo" value="颠倒" onClick="reverseNode(document.body)"></p> </body> </html> 例子4-- sample4_2.htm: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>无标题文档</title> <script language="javascript"> function reverseTable() { var node = document.getElementsByTagName("table")[0]; //第一个表格 var child = node.getElementsByTagName("tr"); //取得表格内的所有行 var newChild = new Array(); //定义缓存数组,保存行内容 for(var i=0;i<child.length;i++) { newChild[i] = child[i].firstChild.innerHTML; } node.removeChild(node.childNodes[0]); //删除全部单元行 var header = node.createTHead(); //新建表格行头 for(var i=0;i<newChild.length;i++) { var headerrow = header.insertRow(i); //插入一个单元行 var cell = headerrow.insertCell(0); //在单元行中插入一个单元格 //在单元格中创建TextNode节点 cell.appendChild(document.createTextNode(newChild[newChild.length-i-1])); } } </script> </head> <body> <table width="200" border="1" cellpadding="4" cellspacing="0"> <tr> <td height="25">第一行</td> </tr> <tr> <td height="25">第二行</td> </tr> <tr> <td height="25">第三行</td> </tr> <tr> <td height="25">第四行</td> </tr> </table> <br> <input type="button" name="reverse" value="开始颠倒" onClick="reverseTable()"> </body> </html> 例子5 -- sample4_3.htm: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>无标题文档</title> <script language="javascript"> function replaceContent() { var table1 = document.getElementsByTagName("table")[0]; var table2 = document.getElementsByTagName("table")[1]; var kid1 = table1.firstChild.firstChild.firstChild; //定位到<td>节点 var kid2 = table2.firstChild.firstChild.firstChild; //定位到<td>节点 var repKid = kid2.firstChild; //定位到表格二<td>内含的TextNode节点 try { //用表格二的单元格内容替换表格一的单元格内容,表格二变成没有单元格内容 kid1.replaceChild(repKid,kid1.firstChild); //下面注释如果开放,将出现object error,因为表格二已经被改变 //kid2.replaceChild(kid1.firstChild,kid2.firstChild); }catch(e){ alert(e); } } </script> </head> <body> <table width="200" border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td>表格一</td> </tr> </tbody> </table> <br> <table width="200" border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td>表格二</td> </tr> </tbody> </table> <br> <input type="button" name="replaceNode" value="替换" onClick="replaceContent()"> </body> </html> 注意,当执行kid1.replaceChild(repKid,kid1.firstChild);的时候,table2的子节点已经被转移到table1了,table2已经没有子节点,不能再调用table2的子节点。看看代码的注释,试着运行一下,应该就知道文档是怎么改变的了。 D、往文档添加新内容 例子6 – sample5_1.htm: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>无标题文档</title> <script language="javascript"> function insertStr() { var f = document.form1; var value = f.str.value; if(value!="") { // 从最终的TextNode节点开始,慢慢形成<tbody>结构 var text = document.createTextNode(value); //新建一个TextNode节点 var td = document.createElement("td"); //新建一个td类型的Element节点 var tr = document.createElement("tr"); //新建一个tr类型的Element节点 var tbody = document.createElement("tbody"); //新建一个tbody类型的Element节点 td.appendChild(text); //将节点text加入td中 tr.appendChild(td); //将节点td加入tr中 tbody.appendChild(tr); //将节点tr加入tbody中 var parNode = document.getElementById("table1"); //定位到table上 parNode.insertBefore(tbody,parNode.firstChild); //将节点tbody插入到节点顶部 //parNode.appendChild(tbody); //将节点tbody加入节点尾部 } } </script> </head> <body> <form name="form1" method="post" action=""> <input name="str" type="text" id="str" value=""> <input name="insert" type="button" id="insert" value="留言" onClick="insertStr()"> </form> <table width="400" border="1" cellspacing="0" cellpadding="0" id="table1"> <tbody> <tr> <td height="25">网友留言列表:</td> </tr> </tbody> </table> </body> </html> 我们之前说过,<table>的子节点是<tbody>,<tbody>的子节点才是<tr>,<tr>是<td>的父节点,最后<td>内部的TextNode节点。所以,往<table>增加单元格行要逐级形成,就像往树里面添加一个枝桠一样,要有叶子有径。看看,这个留言簿是不是很简单啊。这个例子同时也演示了往<table>表格标记里面增加内容的另一种方法。 <html> |
DOM文档对象模型-HTML
最新推荐文章于 2023-02-14 21:27:24 发布
DOM文档对象模型
2007-01-05 12:19