一、什么是dom?
什么叫dom,dom是文档对象模型(document object model,是基于浏览器编程(在本教程中,可以说就是dhtml编程)的一套api接口,w3c出台的推荐标准,每个浏览器都有一些细微的差别,其中以mozilla的浏览器最与标准接近。单纯的javascript要结合dom才能做dhtml编程,才能做出漂亮的效果、应用于web。这点几乎与其它的语言无异,正如c/c++需要库支持是一样的道理。否则就是单纯的在语法上做研究了。因此,必须要对dom有一定的认识,才能把javascript应用于web,或你的ria应用当中,因为dhtml本质上就是操作dom树。
以后的编程当中,希望你能够把dhtml.chm这本手册也拿上,如果你需要兼容gecko,把gecko的dom手册也带上。因为api太多,想不起来的接口还可以查这本手册。
如果你要测试浏览器是否是支持dom的,简单的一句就可以判断
<script>
var issupportdom = !!document.getelementbyid; //两个取反,这已经在上节中说过了,意思是强制转型
alert("你的浏览器 " +(issupportdom?"":"不")+ "支持 dom!");
</script>
二、dom树
要注意:dom树的根统一为文档根—document,dom既然是树状结构,那么他们自然有如下的几种关系:
根结点(document)
父结点(parentnode)
子结点(childnodes)
兄弟结点 兄弟结点
(sibling) (sibling)
例子:
假设网页的html如下
程序代码
<html>
<head>
<title>never-online's website</title>
</head>
<body>
<div>tutorial of dhtml and javascript programming</div>
</body>
</html>
我们参照树的概念,画出该html文档结构的dom树:
html
body head
div title
文本 文本
从上面的图示可以看出
html有两个子结点,而html就是这两个子节点的父结点
head有节点title,title下有一个文本节点
doby下有节点div,div下有一个文本节点
三、操作dom树
开篇已经说过,dhtml本质就是操作dom树。如何操作它呢?
假设我要改变上面html文档中div结点的文本,如何做?
程序代码
<html>
<head>
<title>never-online's website</title>
<script>
function changedivtext (strtext) {
var noderoot = document; //这个是根结点
var nodehtml = noderoot.childnodes[0]; //这个是html结点
var nodebody = nodehtml.childnodes[1]; //body结点
var nodediv = nodebody.childnodes[0]; //div结点
var nodetext = nodediv.childnodes[0];//文本结点'
nodetext.data = strtext; //文本节点有data这个属性,因此我们可以改变这个属性,也就成功的操作了dom树中的一个结点了
}
</script>
</head>
<body>
<div>tutorial of dhtml and javascript programming</div>
<input onclick="changedivtext('change?')" type="button" value="change"/>
</body>
</html>
从上面的示例可以看出,我们可以用上面的这种方法操作dom树上的任一节点。(注:1. 跨域除外,跨域通常是在操作frame上,简单的说,就是两个frame不属于同一域名。2.上面的操作为了演示,采用的方法是从根结点一直到文本结点的遍历,在dom方法上,有更简洁的方法,这些以后会有更多示例加以说明,下文中也会有介绍)
三、dom节点。
细心些的朋友也许发现了,在上面写的html代码时用<>与</>包函起来的就是一个结点,事实上是这样的吗?答案是否定的。下面就是说说节点类型,否则在有的时候是会犯错误的。比如,你把上面的代码放到mozilla firefox的浏览器里运行一下,就会知道了。
dom中的结点类型比较多,这里写一些在html文档中(注:xml也是dom树结构)常见的几种结点类型。
1、document_node
(document)文档根结点类型,该枚举型的值是9.
2、element_node
(element)元素结点类型,该枚举型的值是1。上文中的html, body, div这些结点都是属于该类型。
3、text_node
(text)文本结点类型,该枚举型的值是3。上文中的文本,如:tutorial of dhtml and javascript programming就是属于该类型。
(注:一个空格也就可能是一个文本结点)
通常更需要注意的是文本结点,有可能一个回车,一个空格都是文本结点。这一点以后会碰到,当然,我们也有办法处理,这里先不要急,以后也会说到的。
四、dom常用的api
这些常用的api是要记下来的,当然在非ie的浏览器里也会有效,是符合w3c的。这些api在以后的编程中会常常用到。正如每个编程平台所提供的api一样,常用必须记下来,节省时间从而提高编程效率。只写几个最常用的,其它的api会在以后的示例中写出。由浅而深,从易到难嘛。
1、获取element_node,元素节点
1)、方法:document.getelementbyid(元素的id),返回值为元素的节点引用。可以假想一下这个api的原理:象我们上面所做的是遍历每个节点(从根到我们所需结点),这个api,也可以想成是从根遍历,查询每个结点(空白结点和空结点除外),并获取该结点的id是否为指定的id,如果是的话,就返回这个结点(注:在js中,数组和对象是引用类型),如果没有就返回空。我们可以写写这个代码,帮助我们理解document.getelementbyid。下面是一个简单遍历body中元素的示例。
<html>
<head>
<title>never-online's website</title>
<script>
function mygetelementbyid (id) {
var noderoot = document; //这个是根结点
var nodehtml = noderoot.childnodes[0]; //这个是html结点
var nodebody = nodehtml.childnodes[1]; //body结点
var bodychild = nodebody.childnodes; //body的孩子
for (var i=0; i<bodychild.length; i++) { //简单的遍历(指body的孩子下的深度为1)
if (bodychild[i].id==id) return bodychild[i];
};
return null;
}
function testgetelementbyid (id) {
var node = mygetelementbyid(id);
if (node!=null) {
alert("找到结点 "+id+"!");
alert(node.childnodes[0].data);
} else {
alert("没有找到结点 "+id+".");
}
}
</script>
</head>
<body>
<div id="atestnode"></div>
<div id="textnode">tutorial of dhtml and javascript programming</div>
<input onclick="testgetelementbyid('textnode')" type="button" value="change"/>
</body>
</html>
2)、属性:object.innerhtml,返回值:一个节点内的html值。该属性为可写属性。它虽然不是获取结点,但经常与获取结点相结合,所以我把它放在获取结点这一类,它的属性就类似于是纯文本节点属性中的data。以document.getelementbyid和object.innerhtml这两个api为例,我们就可以把上面所写的代码简化一下了,示例如下:
<html>
<head>
<title>never-online's website</title>
<script>
function changedivtext (strtext) {
var node = document.getelementbyid("textnode");
node.innerhtml = strtext;
}
</script>
</head>
<body>
<div id="textnode">tutorial of dhtml and javascript programming</div>
<input onclick="changedivtext('change?')" type="button" value="change"/>
</body>
</html>
3)、方法:object.getelementsbytagname(标签的名字),返回一个集合,该集合的把有元素都是有指定标签的元素。访问集合里的元素,可以用下标来访问。语法里的object,是指document(根)或者是一个element_node。这个的原理示例我就不写了,可以作为一个作业,大家可以写写。这里写一些具体应用。如上例,我们还可以这样写。
<html>
<head>
<title>never-online's website</title>
<script>
function changedivtext (strtext) {
var node = document.getelementsbytagname("div");
node[0].innerhtml = strtext;
}
</script>
</head>
<body>
<div>tutorial of dhtml and javascript programming</div>
<input onclick="changedivtext('change?')" type="button" value="change"/>
</body>
</html>
再取一个例子,注意,body下的结点深度为2。
<html>
<head>
<title>never-online's website</title>
<script>
function changedivtext (strtext) {
var node = document.getelementbyid("nodetest");
var mynode = node.getelementsbytagname("div");
mynode[0].innerhtml = strtext;
}
</script>
</head>
<body>
<div id="nodetest">
<div>tutorial of dhtml and javascript programming</div>
<input onclick="changedivtext('change?')" type="button" value="change"/>
</div>
</body>
</html>
二、动态创建与插入结点
1)、创建结点对象。document.createelement(tagname),tagname指的是一个标签,比如一个div,就是document.createelement("div"),它返回的是这个结点的引用。
2)、在body的尾部插入结点用document.body.appendchild(object),为了容易理解,下面这个示例,我用了ie专有的属性object.outerhtml,得到一个该元素的html标签内容(包括自身),这样会更容易看到效果。
<html>
<head>
<title>never-online's website</title>
<script>
function insertnode (strtext) {
alert("插入元素前的body html:\n" +document.body.outerhtml);
var node = document.createelement("div");
node.innerhtml = strtext;
document.body.appendchild(node);
alert("插入元素后的body html:\n" +document.body.outerhtml);
}
</script>
</head>
<body>
<div>tutorial of dhtml and javascript programming</div>
<input onclick="insertnode('change?')" type="button" value="change"/>
</body>
</html>
[/htm]
3)、在元素处插入结点。object.insertbefore(onewnode [, ochildnode]),onewnode为一个我们创建的结点,ochildnode是可选的,为object下的一个子节点。同样的,为了看到效果,我也用了outerhtml。示例
[html]
<html>
<head>
<title>never-online's website</title>
<script>
function insertnode (strtext) {
alert("插入元素前的body html:\n" +document.body.outerhtml);
var node = document.createelement("div");
var mynode = document.getelementbyid("textnode");
node.innerhtml = strtext;
document.body.insertbefore(node,mynode);
alert("插入元素后的body html:\n" +document.body.outerhtml);
}
</script>
</head>
<body>
<div id="textnode">tutorial of dhtml and javascript programming</div>
<input onclick="insertnode('change?')" type="button" value="change"/>
</body>
</html>
三、移除结点。
1) object.parentnode.removechild(ochildnode),这个就是语法,下面看示例。
<html>
<head>
<title>never-online's website</title>
<script>
function insertnode (strtext) {
alert("插入元素前的body html:\n" +document.body.outerhtml);
var node = document.createelement("div");
var mynode = document.getelementbyid("textnode");
node.innerhtml = strtext;
document.body.insertbefore(node,mynode);
alert("插入元素后的body html:\n" +document.body.outerhtml);
}
function removecreatenode() {
alert("移除元素前的body html:\n" +document.body.outerhtml);
var node = document.getelementbyid("textnode");
node.parentnode.removechild(node);
alert("移除元素前的body html:\n" +document.body.outerhtml);
}
</script>
</head>
<body>
<div id="textnode">tutorial of dhtml and javascript programming</div>
<input onclick="insertnode('change?')" type="button" value="insert"/>
<input onclick="removecreatenode()" type="button" value="remove"/>
</body>
</html>
这一节就先写到这里,下一节我们就可以用这几个简单的api做许多事情了,几个api就可以写出很多效果
