DOM Node

  DOM 定义了一个 Node 接口,该接口酱油 DOM 中的所有节点类型实现。这个 Node 接口在 JavaScript 中是作为 Node 类型实现的。

  JS 中所有节点类型都继承自 Node 类型,因此所有节点类型都共享着相同的基本属性和方法。

  每个节点都有一个 nodeType 属性,用以标明节点的类型。节点类型由 在 Node 类型中定义的下列 12 个数值常量来标识,任何节点类型必居其一:

  要了解节点的具体信息,可以使用 NodeName 和 NodeValue 这两个属性。对于元素节点,nodeName 中始终保存的都是元素的标签名,而 nodeValue 的值始终为 null。

  文档中所有节点都存在关系,可以用传统的家族关系来描述。在 HTML 中, 可以将 body 看成是 html 的子元素;html 也可以看成是 body 的父元素;head 则可以看成是 body 的同胞元素,因为他们都是 html 的直接子元素。

  每一个节点都有 childNodes 属性,保存着一个 NodeLIst 对象,NodeList 是一种类数组对象,用于保存一组有序的节点;可以使用方括号的语法来访问 NodeList 的值,也有 length 属性。

  NodeList 对象的独特之处在于,它实际上是基于 DOM 结构动态执行查询的结果,因此 DOM 结构的变化能够自动反应在 NodeList 对象中。我们常说 NodeList 是有生命,有呼吸的对象,而不是我们第一次访问它们的某个瞬间拍摄下来的一张快照。

  除了方括号,也可以使用 item() 方法来访问 NodeList 中的节点。为了操作方便,可以使用 Array.prototype.slice() 方法将其转换为数组:

  可以看到 NodeList 对象无法使用 map() 等方法来操作,转成数组后会更方便操作。

 

  每一个节点都有 parentNode 属性,该属性指向文档树中的父节点,包含在 childNodes 列表中的所有节点都具有相同的父节点。

  此外,包含在 childNodes 列表中的每个节点相互之间都是同胞节点。通过使用每个节点的 previousSibling 和 nextSubling 属性,可以访问同一列表中的其他节点。

  列表中第一个节点的 previousSibling 属性值为 null,最后一个节点的 nextSibling 值为 null。

 

  父节点与其第一个和最后一个子节点之间也存在着特殊关系;firstChild 值始终等于 childNodes[0] 的值,而 lastChild 值始终等于 childNodes[childNodes.length - 1] 的值。在只有一个节点的情况下,firstChild 和lastChild 指向同一个节点;如果没有子节点,则 firstChild 和 lastChild 值为  null。明确这些关系对我们查找和访问文档结构中的节点提供了极大的便利。

 

  操作节点

  因为关系指针都是只读的,所以 DOM 提供了一些操作节点的方法,其中最常用的是 appendChild() ,用于向 childNodes 列表末尾添加一个节点。添加节点后,childNodes 的新增节点,父节点以及以前的最后一个子节点的关系指针都会相应的得到更新。更新完成后,appendChild() 返回新增的节点。

  

  如果传入到 appendChild() 中的节点已经是文档的一部分了,那结果就是将该节点从原来的位置转移到新位置。即使可以将 DOM 树看成是由一系列指针连接起来的,但任何 DOM 节点也不能同时出现在文档中的多个位置上。因此,如果在调用 appendChild() 时传入了父节点的第一个子节点,那么该节点就会成为父节点的最后一个子节点。

  如果需要把节点放在 childNodes 列表中某个特定的位置上,而不是放在末尾,那么可以使用insertBefore() 方法,这个方法接受两个参数:要插入的节点和作为参照的节点。插入节点后,被插入的节点会变成参照节点的前一个同胞节点(previousSibling),同时被方法返回。如果参照节点是 null ,则 inserBefore() 与 appendChild() 执行相同的操作。

  replaiceChild() 插入一个节点时,该节点的所有关系指针都会从被它替换的节点复制过来。

  如果只想移除节点,可以使用 removeChild() 方法。该方法接收一个参数,即要移除的节点。被移除的节点将成为方法的返回值。

  以上四个方法都是某个节点的子节点,也就是说要使用这几个方法,必须先取得其父节点(使用 parentNode 属性) 。另外,并不是所有类型的节点都有子节点,如果在不支持子节点的节点上调用了这些方法,将会导致错误。

 

  其他方法:

  有两个方法是所有类型的节点都有的,第一个就是 clondNode() ,用于创建调用这个方法的节点的一个完全相同的副本。 cloneNode() 方法接受一个布尔值参数,标识是否执行深复制。在参数为 true 的情况下,执行深复制,也就是复制节点及其整个子节点树;在参数为 false 时,执行浅复制,即只复制节点本身。复制后返回的节点副本属于文档所有,单并没有为它指定父节点。因此,这个节点副本就成了一个“孤儿”,除非通过 appendChild()、insertBefore() 或 replaceChild() 将它添加到文档中。

  如果我们已经将 ul 元素的引用保存在了变量 myList 中,那么可以通过下列代码看出 cloneNode() 方法的两种模式:

 

  最后一个方法是 normalize() ,这个方法唯一的作用就是处理文档树中的文本节点。由于解析器的实现或 DOM 操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点的情况。当在某个节点上调用这个方法时,就会在该节点的后代节点中查找上述两种情况。如果找到了空文本节点,则删除它;如果找到了相邻的文本节点,则将它们合并为一个文本节点。

posted @ 2021-04-25 14:32  名字不好起啊  阅读(101)  评论(0编辑  收藏  举报