一 节点(Node)与元素(Element)
在HTML中每一个tag都被看成一个Element,而Element也是Node类型。也就是说元素仅仅是一种特殊的节点,在HTML常用的节点类型有:
1. 元素节点 (整个tag标签)
2. 属性节点 (标签里面的属性)
3. 文本节点 (始末标签里面的文本)
4. 文档节点 (整个文档对应document对象)
下面文档
<html>
<head>
<title>文档标题</title>
</head>
<body>
<a href="#">我的链接</a>
<h1>我的标题</h1>
</body>
</html>
的DOM树如下
nodeType | nodeName | nodeValue | |
文档节点 | 9 | #document | 不可用 |
元素节点 | 1 | 标签名称 | 不可用 |
属性节点 | 2 | 属性名称 | 属性值 |
文本节点 | 3 | #text | 文本 |
三 几个特殊的节点
1. document节点
这个就是文档节点,所有节点的祖先。对全局的节点的访问需要使用它。
2. html节点
document节点指整个文档节点,但有时候html节点也可以等效于整个文档。因为我们获取的信息都在html标签里面。
要注意html并非总是document的第一个子节点,因为有时候我们会在html上加上<doctype>。
获取html节点可以用 var oHtml = document.documentElement
3. body节点
一个html节点不会多余两个子节点(html应该总写上head跟body),一个是head,一个是body.。所以获取它们的方法是(对文档的操作应该在文档加载完毕后,不要在body还未加载就进行dom操作):
var oHead = oHtml.firstChild
var oBody = oHtml.lastChild 或 var oBody = document.body
四 getElementById与通用元素选择器
在所有的DOM查找中可能getElementById这种方式最常用了,但是正如它的名字一样它只能返回一个元素,对于存在同名ID的元素这种方式就不太实用了。另外该方法只有document节点可以调用,元素节点是没有这个方法的。
有时候我们需要查找页面上所有的元素,当然你可以使用遍历然后判断是否是元素节点这种方法。幸运的是css选择器为我们提供了通用元素选择器*,只需要getElementsByTagName("*")就可以获取页面全部元素了。
五 appendChild方法
这里列出这个,只想说明一点。此方法的调用不仅仅具有把节点绑定到目标节点作为其子节点,同时还会删掉其原来的父节点的联系。如下面的代码,没有显示在form1删掉fom1_text,但是appendChild后在form1下面已经不存在fom1_text了
var form1 = document.getElementById("form1");
var form2 = document.getElementById("form2");
var fom1_text = document.getElementById("fom1_text");
form2.appendChild(fom1_text);
六 DOM树构建完成事件
这里的DOM事件是指与DOM树操作相关的事件,如:节点的删除,添加,修改均会促发相应的事件,但是这些事件基本不用,在引入了jQuery之后有一个我们经常就用到了,那就是DOMContentLoaded.
这个事件在DOM树创建完毕之后促发,DOM树创建完毕不等于页面载入完毕,因为页面还需要载入图片的信息的。所以它是先与window.onload事件的。测试代码:
window.addEventListener("load",function(){
alert("文档加载完毕");
},false);
document.addEventListener("DOMContentLoaded",function(){
alert("DOM树加载完毕");
},false);
七 文档碎片
每次对文档进行操作,如添加,删除,修改节点等操作都会使DOM树重构。如果我们添加100个节点将会引发100次DOM树重构(不会再促发DOMContentLoaded事件),这个效率是十分低下的。
可以用一种文档碎片的方法来解决这个问题,它的思路是将这些节点先放在一个叫文档碎片的地方,然后一次性的更新到目标文档里面。那么上面的100次DOM树重构就变成了一次。它除了有这个功能,它的临时存储空间的概念也会使我们的程序逻辑更加清晰,如下面的表格排序:
<input type="button" value="test" id="btm_id"/>
<table border="1" id="table_id">
<tr><td>4</td></tr>
<tr><td>2</td></tr>
<tr><td>5</td></tr>
<tr><td>1</td></tr>
<tr><td>3</td></tr>
</table>
document.addEventListener("DOMContentLoaded",function(){
alert("DOM树加载完毕");
document.getElementById("btm_id").addEventListener("click",function(){
//创建文档碎片
var oFragment = document.createDocumentFragment();
var oTable = document.getElementById("table_id");
var rows = oTable.getElementsByTagName("tr");
//创建TR数组
var aTrs = [];
for(var i=0;i<rows.length;i++) aTrs.push(rows[i]);
//排序,从小倒大
aTrs.sort(function(oTr1,oTr2){
var n1 = parseInt(oTr1.cells[0].firstChild.nodeValue);
var n2 = parseInt(oTr2.cells[0].firstChild.nodeValue);
if(n1 < n2) return -1;
else if(n1 > n2) return 1;
else return 0;
});
//添加到文档碎片
for(var i=0;i<aTrs.length;i++) oFragment.appendChild(aTrs[i]);
//添加到表格节点下,更新文档
oTable.appendChild(oFragment);
},false);
},false);