欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaScript中对DOM节点的访问、创建、修改、删除

程序员文章站 2022-10-13 22:02:07
dom dom就是document object model的缩写。文档对象模型是把xml或html以树节点为表现形式的文档。用dom方法和属性,你可以访问,修改,删除页...

dom
dom就是document object model的缩写。文档对象模型是把xml或html以树节点为表现形式的文档。用dom方法和属性,你可以访问,修改,删除页面上任意一个元素,也是可以添加一个元素。dom是独立于语言的api,可以被任意语言所实现,当然也包括了javascript
看看下面的一个文本。

<!doctype html public "-//w3c//dtd xhtml 1.0 strict//en" 
  "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd"> 
<html> 
 <head> 
  <title>my page</title> 
 </head> 
 <body> 
  <p class="opener">first paragraph</p> 
  <p><em>second</em> paragraph</p> 
  <p id="closer">final</p> 
 </body> 
</html> 

 
我们来看看第二段

<p><em>second</em> paragraph</p> 

可以看到这是个p标签。它被包含在body标签中。所以说body是p的父节点,p是子节点。第一段和第三段也是body的子节点。它们都是第二段的兄弟节点。这个em标签是第二段p的子节点。因此p就是它的父节点。父子节点关系能描绘出像树一样的关系。所以叫做dom结构树(dom tree).
 
core dom 和 html dom
我们已经知道dom可以描绘出html和xml文档。事实上html文档就是xml文档,只不过更为规范些。因此作为dom level 1的一部分,core dom规范适用于所有xml文档以及html dom规范扩展了core dom.当然html dom不能适用于所有的xml文档,仅仅适用于html文档。让我们来看看core dom和html dom的构造器。
 
构造器关系

JavaScript中对DOM节点的访问、创建、修改、删除

访问dom节点
当要验证表单或者更换图片之前,我们要知道怎么样访问元素(element.)。有很多方法获取元素。
 
document节点
通过document我们可以访问当前的文档。我们可以通过firebugs(火狐插件),来查看document的属性和方法。
 
所有的节点都有nodetype,nodename,nodevalue的属性。我们来看看document的nodetype是什么

document.nodetype;//9 

 一共有12节点类型。document是9。常用的是元素(element:1),属性(attribute:2),文本(text:3)。
节点还有名称。对于html标签。节点名称就是标签名称。文本节点(text)的名字是#text.文档节点(document)的名字是#document.
 
节点也有值。对于文本节点,值就是文本。document的值为null
 
documentelement
xml都会有个root节点来包文档包含起来。对于html文档。root节点就是html标签。访问root节点。可以用documentelement的属性。

document.documentelement;//<html> 
document.documentelement.nodetype;//1 
document.documentelement.nodename;//html 
document.documentelement.tagname;//对于element,nodename和tagname相同 

 
 child nodes
为了确定是否包含子节点我们可以用如下方法

document.documentelement.haschildnodes();//true 

 html有两个子节点。

document.documentelement.childnodes.length;//2 
 
document.documentelement.childnodes[0];//<head> 
 
document.documentelement.childnodes[1];//<body> 

  也可以通过子节点访问父节点

document.documentelement.childnodes[1].parentnode;//<html> 

 我们把body的引用赋值变量

var bd = document.documentelement.childnodes[1]; 
bd.childnodes.length;//9 

 让我们看看body的结构

<body> 
 <p class="opener">first paragraph</p> 
 <p><em>second</em> paragraph</p> 
 <p id="closer">final</p> 
 <!-- and that's about it --> 
</body>

  
 为什么子节点个数为9个呢。
 首先是4个p还有一个注释一共4个。
 4个节点包含了3个空白的节点。这就7个。
 第8个在body和第一个p之间的空白节点。
 第9个就是在注释与</body>之间的空白节点。
 一共9个节点。
 
属性
因为第一节点是空白节点,所以第二个节点才是第一个p标签。

bd.childnodes[1];//  <p class="opener"> 

可以查看它是否有属性

bd.childnodes[1].hasattributes();//true 

也可以查看attributes的个数

bd.childnodes[1].attributes.length;//1 
 
//可以用index和名字来访问属性,也可以用getattribute方法。 
bd.childnodes[1].attributes[0].nodename;//class 
 
bd.childnodes[1].attributes[0].nodevalue;//opener 
 
bd.childnodes[1].attributes['class'].nodevalue;//opener 
 
bd.childnodes[1].getattribute('class');//opener 

 访问标签里的内容
让我们看看第一个标签p
你可以用textcontent属性来访问。要注意的是,在ie浏览器中并不存在textcontent,请用innertext来替换,结果都是一样的。

bg.childnodes[1].textcontent;// "first paragraph" 

还有一个属性是innerhtml.这并不是dom的规范。但是主流浏览器都支持这个属性。它返回的是html代码。
 

bg.childnodes[1].innerhtml;// "first paragraph" 

第一段没有html代码,所以结果和textcontent(ie里是innertext)是一样的。来看下第二段包含html代码的标签

bd.childnodes[3].innerhtml;//"<em>second</em> paragraph" 
 
bd.childnodes[3].textcontent;//second paragraph 

 
另一种方法可以获取文本节点,然后再取nodevalue属性,代码如下

bd.childnodes[1].childnodes.length;//1 子节点个数 
 
bd.childnodes[1].childnodes[0].nodename;// 节点名称 #text 
 
bd.childnodes[1].childnodes[0].nodevalue;//节点值 first paragraph 

 
快速访问dom
通过childnodes,parentnode,nodename,nodevalue以及attributes,可以访问文档任意的节点了。但是在实际运用过程中,文本节点是比较讨厌的。如果文本改变了,有可能就影响脚本了。还有如果dom树足够的深入,那么访问起来的确有些不方便。幸好我们可以用更为方便的方法来访问节点。这些方法是

getelementsbytagname()
getelementsbyname()
getelementbyid()

首先说下getelementsbytagname()
通过一个标签名称(tag name)来获取一个html元素的集合。例子如下

document.getelementsbytagname('p').length;//3 

因为返回的是个集合,我们可以用过数组下标的形式来访问或者通过item方法。比较一下还是推荐用数组的访问方法。更简单一些。

document.getelementsbytagname('p')[0];// <p class="opener"> 
document.getelementsbytagname('p').item(0);//和上面的结果一样 
 
document.getelementsbytagname('p')[0].innerhtml;//first paragraph 

 
访问元素的属性,可以用attributes集合。但是更简单的方法是直接作为一个属性来访问就行。看个例子

document.getelementsbytagname('p')[2].id;//closer 

要注意的是,class属性不能正常的使用。。要用classname。因为class在javascript规范中是保留字。

document.getelementsbytagname('p')[0].classname;//opener 

我们可以用如下方法访问页面所有元素

<span style="color: #ff0000;">document.getelementsbytagname('*').length;//9</span> 

注意:在ie早期的版本不支持上述方法。可以用document.all来取代。ie7已经支持了,但是返回的是所有节点(node),而不仅仅是元素节点(element nodes)。
 
 
siblings, body, first, last child
nextsibling和previoussibling是两个比较方便访问dom的方法。用来访问相邻的节点的。例子如下

var para = document.getelementbyid('closer') 
para.nextsibling;//"\n" 
para.previoussibling;//"\n" 
para.previoussibling.previoussibling;//<p> 
para.previoussibling.previoussibling.previoussibling;//"\n" 
para.previoussibling.previoussibling.nextsibling.nextsibling;// <p id="closer"> 

 
body 用来访问body元素的。

document.body;//<body> 

firstchild 和lastchild 。firstchild是和childnodes[0]一样.lastchild和 childnodes[childnodes.length - 1]一样。
 
遍历dom
通过以上的学习,我们可以写个函数,用来遍历dom

function walkdom(n) { 
 do { 
  alert(n); 
  if (n.haschildnodes()) { 
   walkdom(n.firstchild) 
  }   
 } while (n = n.nextsibling) 
} 
 
walkdom(document.body);//测试 

修改节点
下面来看看dom节点的修改。
先获取要改变的节点。

var my = document.getelementbyid('closer'); 

非常容易更改这个元素的属性。我们可以更改innerhtml.

my.innerhtml = 'final';//final 

因为innerhtml可以写入html,所以我们来修改html。

my.innerhtml = '<em>my</em> final';//<em>my</em> fnal 

em标签已经成为dom树的一部分了。我们可以测试一下

my.firstchild;//<em> 
my.firstchild.firstchild;//my 

我们也可以通过nodevalue来改变值。

my.firstchild.firstchild.nodevalue = 'your';//your 

 
修改样式
大部分修改节点可能都是修改样式。元素节点有style属性用来修改样式。style的属性和css属性是一一对应的。如下代码

my.style.border = "1px solid red"; 

css属性很多都有破折号("-"),如padding-top,这在javascript中是不合法的。这样的话一定要省略波折号并把第二个词的开头字母大写,规范如下。 margin-left变为marginleft。依此类推

my.style.fontweight = 'bold'; 

我们还可以修改其他的属性,无论这些属性是否被初始化。

my.align = "right"; 
my.name = 'myname'; 
my.id = 'further'; 
my;//<p id="further" align="right" style="border: 1px solid red; font-weight: bold;"> 

 
创建节点

为了创建一个新的节点,可以使用createelement和createtextnode.如果新建完成,可以用appendchild()把节点添加到dom树中。
创建一个元素p,并把设置innerhtml属性

var myp = document.createelement('p'); 
myp.innerhtml = 'yet another'; 

 
元素p建完成了,就可以随意修改添加属性了

myp.style.border = '2px dotted blue' 

 接下来可以用appendchild把新的节点添加到dom树中的。

document.body.appendchild(myp) 

 
使用dom的方法
用innerhtml方法的确很简单,我们可以用纯的dom方法来实现上面的功能。

  • 新建一个文本节点(yet another)
  • 新建一个段落
  • 把文本节点添加到段落中。
  • 把段落添加到body中
// 创建p 
var myp = document.createelement('p'); 
// 创建一个文本节点 
var myt = document.createtextnode('one more paragraph') 
myp.appendchild(myt); 
// 创建一个strong元素 
var str = document.createelement('strong'); 
str.appendchild(document.createtextnode('bold')); 
// 把strong元素添加到p中 
myp.appendchild(str); 
// 把p元素添加到body中 
document.body.appendchild(myp); 
//结果<p>one more paragraph<strong>bold</strong></p> 
 clonenode()

另一种新建节点的方法是,我们可以用clonenode来复制一个节点。clonenode()可以传入一个boolean参数。如果为true就是深度复制,包括他的子节点,false,仅仅复制自己。
 
首先获取要复制的元素。

var el = document.getelementsbytagname('p')[1];//<p><em>second</em> paragraph</p> 

先不用深度复制。

document.body.appendchild(el.clonenode(false)) 

我们发现页面并没有变化,因为仅仅复制的是元素p。和下面的效果一样。

document.body.appendchild(document.createelement('p')); 

如果用深度复制,包括p下面所有的子节点都会被复制。当然包括文本节点和em元素。

document.body.appendchild(el.clonenode(true)) 

 
insertbefore()
用appendchild,就是把元素添加到最后。而insertbefore方法可以更精确控制插入元素的位置。

elementnode.insertbefore(new_node,existing_node) 

实例

document.body.insertbefore( 
 document.createtextnode('boo!'), 
 document.body.firstchild 
); 

 
意思就是新建一个文本节点,把它作为body元素的第一个节点。
 
 
删除节点

要从dom树删除一个节点,我们可以使用removechild().我们来看看要操作的html

<body> 
 <p class="opener">first paragraph</p> 
 <p><em>second</em> paragraph</p> 
 <p id="closer">final</p> 
 <!-- and that's about it --> 
</body> 

来看看下面代码,删除第二段

var myp = document.getelementsbytagname('p')[1]; 
var removed = document.body.removechild(myp); 

removed节点就是删除的节点。以后还可以用这删除的节点。
 
我们也可以用replacechild()方法。这个方法是删除一个节点,并用另一个节点替代。当执行上个删除节点操作之后,结果如下

<body> 
 <p class="opener">first paragraph</p> 
 <p id="closer">final</p> 
 <!-- and that's about it --> 
</body> 

 我们来看看replacechild的使用。我们把上一个删除节点来替代第二个p

var replaced = document.body.replacechild(removed, p); 

 和removechild返回一样。replaced就是移除的节点。现在结果为

<body> 
 <p class="opener">first paragraph</p> 
 <p><em>second</em> paragraph</p> 
 <!-- and that's about it --> 
</body>