深入理解DOM之节点关系及节点操作

节点关系

文档中的节点关系可以用我们经常用到的家族来表示,每个文档树都像是家谱一样。

例如html中节点元素的关系。

例如html中节点元素的关系。
<!DOCTYPE html>
<html>
  <head> 
  </head>
  <body>
  </body>
</html>

其中,<body>是<html>的子元素,<head>是<body>的同胞元素。

每个节点都有一个childNode属性,其中包含一个NodeList对象。

 NodeList

NodeList是一种类数组对象,其中保存了一组有序的节点(可能你现在还不明白这个有序节点组是什么,别急,先看看后面),通过下标位置来访问这些节点。

注意:它与数组基本相同,使用[]语法访问,也可以访问length等属性,但它不是Array的实例,它是基于DOM结构动态执行查询的结果,所以DOM的结构能自动反映在NodeList中,且会更新。

通过数组形式或item()来访问保存在NodeList中的节点:

let a=someNode.childNode[0]//使用数组形式访问
let b=someNode.childNode.item(0)//使用item()访问

也可以使用length来取得当前nodelist所包含的节点数量,取得的结果为访问NodeList那一刻时取得的length值。

父节点与子节点

每个节点都包括一个parentNode属性,该属性指向该节点的父节点,同一个childNode的NodeList中的所有节点,都有相同的父节点,而childNode的NodeList中的节点之间是同胞节点。

这样有些绕,话不多说,上图!

可以直观的感受到了吧!图中还有nextSibling和previousSibling属性,他们用来访问同一列表(同一childNode中)的节点。

nextSibling:返回某个节点的后一个同胞节点。

previousSibling:返回某节点的(前一个同胞节点)。

注意:列表头节点的previousSibling值为null,尾节点的nextSibling值为null,当列表只有一个节点时,它的previousSibling、nextSibling值都为null。

父节点与子节点也有特殊的关系。

父节点的firstChild和lastChild属性分别指向的是其childNodes的第一个节点和最后一个节点,,只有一个节点时,父节点的firstChild和lastChild指向这个节点,当childNodes为空时,父节点的firstChild和lastChild的值均为null。

了解这些关系,使用上文讲的childNodes属性来访问节点就会变得很方便了。

注意:所有节点都有的最后一个属性是ownerDocument,该属性指向当前文档的文档节点,一般用来直接访问文档树的根节点。

操作节点

我们并不能通过指针来操作文档树,因为文档使用的是关系节点,它们都是只读的,所以DOM提供了一些操作节点的方式。

  • 插入节点

1.1尾部添加

appendChild():向childNode的结尾添加一个节点,它的返回值就是新增的节点。

参数数量:1,即新节点的名字。

var returnedNode=someNode.appendChild(newNode);
alert(returnedNode==newNode)//true
alert(someNode.lastChild==newNode)//true

注意:任何节点不能同时出现在文档的不同位置上。所以,如果进行添加的节点,在文档中存在的话,这个节点就会被提取出来,放到当前的新位置。 

1.2指定位置添加

insertBefore():将新的节点放在特定的位置上,同样返回状态更新后的此节点。

参数数量:2,为要插入的节点名以及作为参照的节点。插入时,新节点会插入到这个参照节点的前面。

如:将新节点插入ChildNodes使它成为第一个节点。

var returnedNode=someNode.insertBefore(newNode,someNode.firstChild)
 alert(returnedNode==newNode)//true
 alert(newNode==someNode.firstChild)//true
  • 删除节点

2.1替换节点

replaceChild():替换节点,新的节点替换旧的节点。

参数数量:2,新节点和要被替换的老节点。

替换完成后,旧节点的一切都将复制给新节点,被替换的节点依旧存在,但在文档中已经没有了它的位置,因为关系指针已经不指向它了,指向的是新的节点。

//替换第一个节点
var returnedNode=someNode.replaceChild(newNode,someNode.firstChild)

2.2移除节点

removeChild():直接删除节点。

参数个数:1,要被移除的节点,这个被移除的节点是此函数的返回值。

与replaceChild()一样,这个被移除的节点仍然存在,只是在文档树中没有了它的位置。

//移除第一个节点
var returnedNode=someNode.removeChild(newNode,someNode.firstChild)

注意:以上的四个方法,在使用时需要取得他们的父节点,例子中的someNode就是,所以这些方法只适用于有子节点的节点,在不支持子节点的节点上使用,会有错误。

  • 其它方法

 cloneNode():创建调用此方法节点的副本。

参数数量:1,布尔类的值,true:深拷贝,false:浅拷贝。

深复制:复制整个节点及其整个childNodes的节点。

浅复制:复制节点本身。

副本返回的节点也归被它复制的文档所有,但是此副本没有父节点,我们可以通过上述的四个方法将它们加入到文档中。

注意:这种复制方法并不会复制添加到DOM节点当中的JS属性、事件等,但是,IE会复制,所以在使用前最好将事件移除。

Normalize():处理文档树中的文本节点。

检查DOM树,出现空的文本节点则删除这个节点,出现相邻的文本节点,则将它们合并。

 

本篇的全部内容到此结束了,关于不同节点类型的详情部分,会有专门的篇幅讲述,想查看更多,就请大家移步哦~~

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/weixin_42309926/article/details/107995359