【翻译作品】JavaScript DOM学习第一章:W3C DOM简介

文档对象模式(Document Object Model DOM)用来描述HTML页面中那些输入框、图片、段落等等元素与最顶级的结构document之间的关系。用适当的方法来选取这些元素,我们就可以改变他们。

在这一章我主要介绍已经被新一代的浏览器所支持的W3C 第一级的DOM。对他的运作做一个大概的了解并且让你知道你可以对他们做什么。

首先是对于DOM的一些建议和DOM设计的目的,然后我会告诉你什么是节点(nodes)并且怎样通过DOM树来遍历节点。接着是如何得到一个特定的节点,以及怎样改变他的值和属性。最后就是DOM的终极目标:怎么创建一个自己的新节点。

 

建议

Level 1DOM是W3C制定的用来提供给任何程序语言来访问XML文档的。不管你用什么语言程序来处理XML文档,只要是Level 1DOM里面的方法和属性就可以。不管是Perl、VBScript还是JavaScript你都可以读取任何你想读取的值并且修改他们。

你们可能会猜到,这段描述的是一种理想情况,差异还是存在的(比如浏览器)。然后这部分内容还是比较少,并且你在JavaScript里学习如何处理XML也对你在其它语言中的学习会有一定的帮助。

从某种程度上也可以讲HTML看做是一种XML文档。只要浏览器能够处理相应的脚本,那么Level 1 DOM也同样在HTML里面可以运行的很好。

你可以读取每一个HTML的标签的文本和属性,你可以删除每一个标签和他们的内容,你还可以实时的在现有的文档里面插入一个新的标签而不用在服务器上修改。

因为设计之初要考虑到修改XML的方方面面,所以对于一般的网页工程师来说有一些方法可能永远也用不上。比如,你可以用它来修改HTML的注释,但是我没有看出来问什么要这样做。同样的还有一些DOM处理DTD/Doctype的内容,你在你的网页设计中并不需要,所以忽略掉,集中注意力在你的日常所需上就好。

 

节点(Nodes)

文档对象模型是一种文档内的多个元素之间怎样相互联系的一种模型。在Level 1 DOM中,每一个对象都是一个节点。所以如果你写:

 

<p>This is a paragraph</p>

 

 

那么你就创建了两个节点:元素P和内容是"This is a paragraph”的文本节点。这个文本节点包含在P元素内,所以可以认为是p节点的子节点。反过来说,p元素就是文本节点的父节点。

如果你写成:

 

<p>This is a <B>Paragraph</B></p>

 

 

那么元素节点p就有两个子节点,其中一个还有他自己的子节点。

最后就是参数节点。(令人困惑的是,他们不算做元素节点的子节点。事实上,在我写这一章的过程中我做过一些测试,IE5根本就不把参数节点当做元素的子节点。)所以:

<P ALIGN="right">This is a <B>paragraph</B></P>


的结构可能是这样的:

              <P> ----------------
| |
-------------- ALIGN
| | |
This is a <B> |
| right
|
paragraph

这就是元素节点,文本节点和参数节点。99%的HTML页面都是由他们组成,你的主要任务也就是如何放置他们。当然还有很多的其他节点,暂且略过。

就像你所了解的,p元素也有他自己的父节点,通常就是document,有时候也可能是一个DIV。所以整个文档都可以看做是一颗由很多的节点组成的树,而且这些节点大多都有自己的子节点。

            <BODY>
|
|-------------------------------------
| |
<P> ---------------- lots more nodes
| |
-------------- ALIGN
| | |
This is a <B> |
| right
|
paragraph

 

遍历DOM树

知道了DOM树的结构,你就可以遍历他来找到你想要的元素。举个例子,假设元素节点p已经存储在变量x中(等一会介绍这是怎么做到的)。这时候如果我们想访问BODY那么:

 

x.parentNode

 

 

我们就得到了x的父元素,然后就可以修改它了。这样可以到达B节点:

 

x.childNode[1]

 

 

childNode是一个包含所有x的子节点的数组。当然,数组是从0开始编号的,所以childNode[0]就是文本节点"This is a " childNode[1]就是B节点。

两个特别的:x.firstChild就表示x的第一个子节点;x.lastChild就表示x的最后一个子节点。

假设p是BODY的第一个子节点,BODY又是document的第一个子节点,所以为了到达B节点,你可以用下面的任意方法:

document.firstChild.firstChild.lastChild;
document.firstChild.childNodes[0].lastChild;
document.firstChild.childNodes[0].childNodes[1];
etc.


甚至是下面这个比较笨的:

document.firstChild.childNodes[0].parentNode.firstChild.childNodes[1];


 

得到一个元素

然而,这样遍历文档实在是太麻烦了。因为Level 1 DOM设计的目标就是允许你修改整个DOM树,所以你必须准确的知道DOM树的结构,这会很快导致一些问题。

所以还有一些方法能够很快的到达你想要的元素。只要你到达了这里,就可以遍历整个DOM树的每一个节点。

让我们继续前面的例子。你想要到达元素B。最简单的办法就是直接跳过去。通过document.getElementByTagName你就能很快的创建一个包含文档内的所有B标签的数组。假设我们的B是第一个,那么你就可以简单的写:

var x = document.getElementsByTagName('B')[0]


x就包含了元素节点B。首先你命令浏览器得到整个文档的所有元素B(document.getElementByTagName(‘B’)) ,然后你选择了第一个文档的第一个元素B([0]),就得到了你想要的。

你也可以写:

var x = document.getElementsByTagName('P')[0].lastChild;


现在你先到了文档的第一个段落P(假设我们的P是第一个元素),然后到达p的最后一个子元素。

最好的能准确到达元素并且不需要DOM结构的办法就是给B一个ID:

<P ALIGN="right">This is a <B ID="hereweare">paragraph</B></P>

现在你就可以简单的写:

var x = document.getElementById('hereweare');


元素B就存储在了x里。

 

修改一个节点

现在我们已经到达了节点,就可以做一些修改了。假设我们想把加粗的文字部分修改为'bold bit of text’。我们需要访问正确的元素然后修改它的nodeValue。现在正确的元素不是元素B而是他的子元素text node:我们想改变的是文字,不是元素。所以可以写:

document.getElementById('hereweare').firstChild.nodeValue='bold bit of text';


元素就改变了。

你可以通过nodeValue来修改任何文本节点或者参数。比如你可以修改段落的ALIGN参数。这也是非常的简单,先找到需要的元素(在这个例子中是B元素的父元素),然后使用setAttribute()方法来设置你想要的值:

function test2(val) {
if (document.getElementById && document.createElement)
{
node = document.getElementById('hereweare').parentNode;
node.setAttribute('align',val);
}
else alert('Your browser doesn\'t support the Level 1 DOM');
}


 

创建和删除元素

修改元素固然有用,但是还是不如创建你需要的元素然后插入到现有的文档中。我可以很简单的在这个段落后面添加一个HR元素然后很简单的删除它。

创建元素使用下面的方法:

var x=document.createElemnt(‘HR’)

这样HR就创建并且存储在x中。第二步就是把x插入到文档之中。我写了一个ID是inserthere的SPAN,我们就把它插入到这。所以我们使用appendChild()方法:

document.getElementById('inserthrhere').appendChild(x);


删除它稍稍有点麻烦。我先创建一个临时变量node来存储SPAN,然后我告诉他移除他的第一个子元素:

 

var node=document.getElementById(‘inserthere’);

node.removeChild(node.childNode[0]);

 

同样的方法我们也可以创建一个新的元素然后添加在ID是hereweare的B元素上。
var x = document.createTextNode(' A new text node has been appended!');
document.getElementById('hereweare').appendChild(x);


你可以试一试,你会注意到用老的办法可能不会移除新加的文本,那是因为他们已经成为分离的两部分了:

           <B>
|
------------
| |
paragraph A new text node
has been appended!

 

(可以通过normalize()来把他们合并,但是IE5不支持)

我不打算告诉你怎么移除它,自己练习会比较有收获

翻译地址:http://www.quirksmode.org/dom/intro.html

posted @ 2010-02-18 14:00  BeiYuu  阅读(...)  评论(... 编辑 收藏