《JavaScript高级程序设计》学习笔记(DOM2)

本文介绍了如何使用JavaScript通过DOM访问和操作HTML文档。主要内容包括访问元素、检测节点类型、处理特性及创建和操作节点等。

 《JavaScript高级程序设计》学习笔记(DOM2)

使用DOM

document对象是BOM的一部分,同时也是HTML DOM的HTMLDocument对象的一种表现形式,反过来说,它也是XML DOM Document对象。JavaScript中的大部分处理DOM的过程都利用document对象。

 

访问相关的节点

在下面的几节中考虑下面的HTML页面:
<html>
 <head>
  <title>DOM</title>
 </head>
 <body>
  <p>hello</p>
 </body>
</html>

访问元素:
var oHtml = document.documentElement; //取得<html/>元素
var oHead = oHtml.firstChild; //取得<head/>元素
var oBody = oHtml.lastChild; //取得<body/>元素
或者使用childNodes特性
var oHead = oHtml.childNodes[0]; //取得<head/>元素
var oBody = oHtml.childNodes[1]; //取得<body/>元素

使用childNodes.length特性来获取子节点的数量:
alert(oHtml.childNodes.length); //2

注意方括号标记其实是NodeList在JavaScript中的简便实现。
实际上正式的从childNodes列表中获取子节点的方法是使用item()方法:
var oHead = oHtml.childNodes.item(0);
var oBody = oHtml.childNodes.item(1);

HTML DOM页定义了document.body作为指向<body/>元素的指针:
var oBody = document.body;

有了oHtml、oHead和oBody这三个变量,就可以先尝试确定它们之间的关系:
alert(oHead.parentNode == oHtml);
alert(oBody.parentNode == oHtml);
alert(oBody.previousSibling == oHead);
alert(oHead.nextSibling == oBody);
alert(oHead.ownerDocument == document);

这一小段代码测试并验证了oBody和oHead的parentNode特性都是指向oHtml变量,同时使用previousSibling和nextSibling特性来建立它们之间的关系。最后一行确认了oHead的ownerDocument特性事实上是指向该文档。

注意:不同浏览器在判断何为Text节点上存在一些差异。某些浏览器,如Mozilla,认为元素之间的空白都是Text节点;而另一些浏览器,如IE,会全部忽略这些空白。因为使用Mozilla方式很难确定哪些空白是Text节点,本书将采用IE的方式。

 

检测节点类型

通过使用nodeType特性检验节点类型:
alert(document.nodeType); //9
alert(document.documentElement.nodeType); //1

这个例子中,document.nodeType返回9,等于Node.DOCUMENT_NODE;同时document. documentElement.nodeType返回1,等于Node.ELEMENT_NODE。
其他可参考XML_DOM

也可以用Node常量来匹配这些值:
alert(document.nodeType == Node.DOCUMENT_NODE); //true
alert(document.documentElement.nodeType == Node.ELEMENT_NODE); //true

这段代码可以在Mozilla 1.0+、Opera 7.0+和Safari 1.0+上正常运行。但是IE不支持这些常量,所以这些代码在IE上会产生错误。

 

处理特性

正如前面提到的,即便Node接口已具有attributes方法,且已被所有类型的节点继承,然而,只有Element节点才能有特性。
Element节点的attributes属性其实是NamedNodeMap,它提供一些用于访问和处理其内容的方法:
getNamedItem(name) 返回nodeName属性值等于name的节点;
removeNamedItem(name) 删除nodeName属性值等于name的节点;
setNamedItem(node) 将node添加到列表中,按其nodeName属性进行索引;
item(pos)  像NodeList一样,返回在位置pos的节点;

请记住这些方法都是返回一个Attr节点,而非特性值。

NamedNodeMap对象也有一个length属性来指示它所包含的节点的数量。

当NamedNodeMap用于表示特性时,其中每个节点都是Attr节点,它的nodeName属性被设置为特性名称,而nodeValue属性被设置为特性的值。
例如,假设有这样一个元素:
<p id="p1">hello</p>

假设变量oP包含指向这个元素的一个引用。于是可以这样访问id特性的值:
var sId = oP.attributes.getNamedItem("id").nodeValue; //p1
或者
var sId = oP.attributes.item(0).nodeValue;

还可以通过给nodeValue属性赋新值来改变id特性:
oP.attributes.getNamedItem("id").nodeValue = "newId";

Attr节点也有一个完全等同于(同时也完全同步于)nodeValue属性的value属性,并且有name属性和nodeName属性保持同步。我们可以随意使用这些属性来修改或变更特性。

因为这个方法有些累赘,DOM又定义了三个元素方法来帮助访问特性:
getAttribute(name) 等于attributes.getNamedItem(name).value;
setAttribute(name, newvalue) 等于attribute.getNamedItem(name).value = newvalue;
removeAttribute(name) 等于attributes.removeNamedItem(name)

要获取前面用的<p/>的id特性,只需这样做:
var sId = oP.getAttribute("id");
更改ID:
oP.setAttribute("id", "newId");

 

访问指定节点

DOM提供一些方法来访问指定的节点:

1. getElementsByTagName()

getElementsByTagName()方法,用来返回一个包含所有的tagName(标签名)特性等于某个指定值的元素的NodeList。在Element对象中,tagName特性总是等于小于号之后紧随的名称。
例如:
var oImgs = document.getElementsByTagName("img");
在把所有图形都存于oImgs后,只需使用方括号标记或者item()方法,就可以像访问子节点那样逐个访问这些节点了:
var oT = oImgs[0];
可以使用一个星号的方法来获取document中的所有元素:
var oE = document.getElementsByTagName("*");

注意:当参数是星号时,IE 6.0并不返回所有的元素。必须使用document.all来替代它。


2. getElementsByName()

getElementsByName(),用来获取所有name特性等于指定值的元素的。
例如:
var oRadios = document.getElementsByName("radioname");
注意返回的是一个数组,只要name属性是"radioname"的所有元素都会获得
然后,就可以像处理其他元素那样处理这些对象引用:
alert(oRadios[0].value);

注意:IE 6.0和Opera 7.5在这个方法的使用上还存在一些错误。首先,它们还会返回id等于给定名称的元素。第二,它们仅仅检查<input/>和<img/>元素。


3. getElementById()

这是HTML DOM定义的第二种方法,它将返回id特性等于指定值的元素。在HTML中,id特性是唯一的——这意味着没有两个元素可以共享同一个id。毫无疑问这是从文档树中获取单个指定元素最快的方法。
例如:
var oDiv = getElementById("divid");

注意:如果给定的ID匹配某个元素的name特性,IE 6.0还会返回这个元素。这是一个bug,也是你必须非常小心的一个问题。

 

创建和操作节点

1. 创建新节点

最常用到的几个方法是:
createDocumentFragment() 创建文档碎片节点
createElement()   创建标签名为tagname的元素
createTextNode()  创建包含文本text的文本节点

2. createElement()、createTextNode()、appendChild()

其中appendChild()方法将给定的节点添加到某个节点的childNodes列表的尾部。
假设有如下HTML页面:
<html>
 <head>
  <title>DOM</title>
 </head>
 <body/>
</html>
用DOM添加 <p>hello</p>
实现步骤:
var oP = document.createElement("p"); //创建<p/>元素
var oText = document.createTextNode("hello"); //创建文本节点
oP.appendChild(oText); //把文本节点加入到元素中
document.body.appendChild(oP); //将这个元素附加到document.body元素上

注意:所有的DOM操作必须在页面完全载入之后才能进行。当页面正在载入时,要向DOM插入相关代码是不可能的,因为在页面完全下载到客户端机器之前,是无法完全构建DOM树的。因为这个原因,必须使用onload事件句柄来执行所有的代码。


3. removeChild()、replaceChild()和insertBefore()

removeChild() 方法 删除节点
这个方法接受一个参数,要删除的节点,然后将这个节点作为函数的返回值返回。
例如:
<html>
 <head>
  <title>DOM</title>
 </head>
 <body>
  <p>hello</p>
 </body>
</html>
删除<p/>节点
var oP = getElementsByTagName("p");
document.body.removeChild(oP);
更好的做法是使用节点的parentNode特性来确保每次你都能访问到它真正的父节点:
oP.parentNode.removeChild(oP);

replaceChild() 方法 替换节点
这个方法有两个参数:被添加的节点和被替换的节点。
例如:
var oOldP = getElementsByTagName("p");
oP.parentNode.replaceChild(oNewP, oOldP);
创建一个新元素oNewP,并用它替换原来元素oOldP

如果想让新消息出现在老消息之后,只要使用appendChild()方法:
oP.parentNode.appendChild(oNewP);

insertBefore() 方法 插入节点
这个方法接受两个参数:要添加的节点和插在哪个节点之前。
例如:
var oOldP = getElementsByTagName("p");
oP.parentNode.insertBefore(oNewP, oOldP);


4. createDocumentFragment()

一旦把节点添加到document.body(或者它的后代节点)中,页面就会更新并反映出这个变化。对于少量的更新,这是很好的,就像在前面的例子中那样。然而,当要向document添加大量数据时,如果逐个添加这些变动,这个过程有可能会十分缓慢。为解决这个问题,可以创建一个文档碎片,把所有的新节点附加其上,然后把文档碎片的内容一次性添加到document中。
例如:
var oFragment = document.createDocumentFragment();
<--对oFragment进行操作--->
document.body.appendChild(oFragment); 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值