Html DOM 学习(未写完)
2 {
3 //for test
4 var df = document.createDocumentFragment();
5 var tr = document.createElement("tr");
6 df.appendChild(tr);
7
8 var td = document.createElement("td");
9 td.innerHTML = "新增";
10 tr.appendChild(td);
11 ......
12 tr.appendChild(td);
13 .......
14 tr.appendChild(td);
15 .........
16 tr.appendChild(td);
17 ........
18 tr.appendChild(td);
19 .....
20 tr.appendChild(td);
21 .......
22 tr.appendChild(td);
23
24 $id("upgradeTbody").insertBefore(df);
25 .....................
26 }
最近工作当中某一功能模块要用到 HTML 的 DOM。由于平时都是用 Jquery 来访问 HTML 节点,怎么通过原生的JS访问或遍历DOM节点已经忘记得一干二净了。唯有用 firebug 查看DOM的节点结构。结构如下图所示:
(图 1 )
注上图每个节点下或许都包含其它节点列表,下图就是节点43 下的节点列表。
(图 2 )
由上两图可知,DOM 的节点结构是一种树型结构,每个节点下面都可能存在它的下一级节点。如下图所示,下图只表示了三级树型结构,但实际上是 N 级树型结构。
(图 3 )
我们访问 DOM 节点时,是由上而下一级级遍历,直到最后找到我们想要的节点。
解析 DOM节点 最基本要用到的函数和方法有 document.getElementById、document.getElementsByName和document.getElementsByTagName。
document.getElementById 只会获取单个节点。而其它二个方法都会获取一个节点列表。
具体举个例子说明是怎样访问 DOM 节点的,请看上 图1 。如上图所示有很多节点,但我只需要获取 43 节点里面的 Table ,然后再将该 Table 显示到页面上。代码如下:
for (var i=0;i<图1.childNodes.length;i++)
{
if(data.childNodes[i].nodeName=="#text") continue;
….
if (data.childNodes[i].nodeName==="DIV")
{
var table = data.childNodes[i].getElementsByTagName("table");
….
break;
}
…..
}
首先我们遍历所有节点列表,判断每个节点名称(nodeName)是否是 “DIV”。如果该节点名称是 “DIV” 则再遍历该节点的下一级节点(data.childNodes[i])。就这样通过一级级遍历最后找到需要的 Table 节点。
获取节点还经常需要用到如下属性或方法。
childNodes 属性可返回 document 的子节点的所有节点列表。
getAttribute() 方法通过名称获取属性的值。
还有parentNode、firstChild、lastChild、nextSibling以及previousSibling。
insertBefore 的用法
通过 JS 在 Tbody 中动态添加一行 Tr ,在 IE6 中遇到一定问题。 IE6 中Tbody 中的 innerHTML 是只读的,这样就不能直接通过 innerHTML 写入新增加行的 Tr 到页面当中。
唯过通到变通一点的方法实现,用 Table 的 outerHTML 重写 Table 的 HTML(代码一)。但这种方法会导致一样问题就是之前存在行的监听事件貌似会清除,又要将之前已经存在的监听事件重新绑定多一次。
这样就做多了很多无谓的工作。
代码一:
2 {
3 var allHtml = $id("upgradeTbody").parentNode.outerHTML.replace("</TBODY>",upgradeTbody3 + "</TBODY>");
4 $id("upgradeTbody").parentNode.outerHTML = allHtml;
5
6 for(key in addNum)
7 {
8 $id("attpk_id2_" + addNum[key]).attachEvent("onchange",attpk_id2_change);
9 $id("delBtn_" + addNum[key]).attachEvent("onclick",delBtn_click);
10 $("#new_startdate2_" + addNum[key]).datepicker();
11 $("#new_enddate2_" + addNum[key]).datepicker();
12 $id("new_startdate2_" + addNum[key]).value = curDate;
13 $id("new_enddate2_" + addNum[key]).value = $id("upgradeTbody").getAttribute("usmEnddate");
14 }
15
16 for(var i=1;i<=listDataLen;i++)
17 {
18 $id("changetype2_" + i).attachEvent("onchange",changetype2Event);
19 if($id("new_startdate2_" + i)!=undefined)
20 $("#new_startdate2_" + i).datepicker();
21 if($id("new_enddate2_" + i)!=undefined)
22 $("#new_enddate2_" + i).datepicker();
23 }
24 }
那时一直只是想到通过 innerHTML 和 outerHTML 来实现新添加表格行的功能。后来才发现了一个方法:insertBefore 应该可以实现我要的功能。代码如下:
2 {
3 //for test
4 var df = document.createDocumentFragment();
5 var tr = document.createElement("tr");
6 df.appendChild(tr);
7
8 var td = document.createElement("td");
9 td.innerHTML = "新增";
10 tr.appendChild(td);
11 ......
12 tr.appendChild(td);
13 .......
14 tr.appendChild(td);
15 .........
16 tr.appendChild(td);
17 ........
18 tr.appendChild(td);
19 .....
20 tr.appendChild(td);
21 .......
22 tr.appendChild(td);
23
24 $id("upgradeTbody").insertBefore(df);
25 .....................
26 }
这样动态添加 DOM ,比之前 innerHTML 和 outerHTM 的方法有一个显著的好处就是未添加前已经存在的行的监听事件不会被清除,这样我们就不用再重新绑定事件了。
另一个例子:http://help.dottoro.com/ljfqstcb.php 好好体会 insertBefore 当有两个参数时的用法。
最近看的关于 DOM 的文章:《1.2.2 文档对象模型(DOM)》 ,从中知道 IE 6 只支持 DOM 1 ,而 FF 等已完成支持 DOM1 并支持 DOM2 的大部分。
---------------------------------------
问题 1 :
var trs = node.getElementsByTagName("table").firstChild.getElementsByTagName("tr");
为什么用 firstChild 会出错呢? 用 firebug 跟踪,trs 的结构如下:
很明显可以看到返回的是一个数组并没有 firstChild 属性。