DOM

最后更新于:2022-04-01 23:53:43

## DOM **1、DOM** 文档对象模型(Document Object Model,**DOM**)是表示和操作HTML和XML文档内容的基础API。 当网页被加载时,浏览器会根据DOM模型,将结构化文档(比如HTML和XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。 如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/65a17e89fc41b994c089e66737967bf7_563x271.png) 上图中的每一个方框是文档的一个节点,它表示一个Node对象,而所有节点组成了节点树(DOM树)。 节点有7种类型: ``` Document:整个文档树的顶层节点 DocumentType:doctype标签(比如) Element:网页的各种HTML标签(比如、等) Attribute:网页元素的属性(比如class="right") Text:标签之间或标签包含的文本 Comment:HTML或XML的注释 DocumentFragment:文档的片段 Document和Element是两个重要的DOM类。 ``` **1.1节点之间的关系** 在一个节点之上的直接节点是其 `父节点` ,在其下一层的直接节点是其 `子节点` 。在同一层上具有相同父节点的节点是 `兄弟节点` 。在一个节点之下的所有层级的一组节点是其 `后代节点` 。一个节点的任何父节点、祖父节点和其上层的所有节点是 `祖先节点` 。 通用的`Document`和`Element`类型与`HTMLDocument`和`HTMLElement`类型之间是有严格区别的。 `Document`类型代表一个HTML或XML文档,`Element`类型代表该文档中的一个元素。 `HTMLDocument`和`HTMLElement`子类只是针对于HTML文档和元素。 `CharacterData`通常是`Text`和`Comment`的祖先,它定义两种节点所共享的方法。 `Attr`节点类型代表XML或HTML属性。 `Element`类型定义了将属性当做“名/值”对使用的方法。 `DocumentFragment`类型在实际文档中并不存在的一种节点,它代表一系列没有常规父节点的节点。 **1.2 选取文档元素** 在JavaScript中,有多种方法选取元素。 - 用指定的id属性 - 用指定的name属性 - 用指定的标签名字 - 用指定的CSS类 - 匹配指定的CSS选择器 **1.2.1 用指定ID选取元素** 任何HTML元素都可以有一个id元素,但在文档中该值必须唯一,即同一个文档中的元素不能出现有相同的ID。可以用`Document`对象的`getElementById()`方法选取特定ID的元素。 ```
document.getElementById('div'); ``` **1.2.2 用指定名字选取元素** 一些HTML元素拥有`name`属性(比如`
、、`等),非唯一,所以多个元素可能有相同的名字。 基于name属性的值选取HTML元素,可以使用`Document`对象的`getElementsByName()`方法,返回一个NodeList对象(类数组对象)。 ``` var inputs = document.getElementsByName('input'); inputs[0].tagName //input ``` 注意:getElementsByName()定义在HTMLDocument类中,而不在Document类中,所以它只针对HTML文档可用,在XML中不可用。 **1.2.3 用指定标签名选取元素** `Document`对象的`getElementsByTagName()`方法可用来选取指定类型(标签名)的所有HTML或XML元素,也是返回一个NodeList对象 ``` document.getElementsByTagName('span') // 选取所有span元素 ``` 给`getElementsByTagName()`传递通配符参数“*”,将获得一个代表文档中所有元素的NodeList对象。 在`Element`类中也同样定义了`getElementsByTagName()`方法,其原理和Document版本是一样的,不过它只选取调用该方法的元素的后代元素。 下面的代码就是查找文档中第一个

元素里面的所有元素。 ``` var p = document.getElementsByTagName('p')[0]; var span = p.getElementsByTagName('span'); ``` **1.2.4 用指定CSS类选取元素** HTML元素的`class`属性值是一个以空格隔开的列表,可以为空或包含多个标识符。 在HTML文档和HTML元素上,我们可以调用`getElementsByClassName()`来选择指定CSS类的元素,它返回一个实时的NodeList对象,包含文档或元素所有匹配的后代节点。 `getElementsByClassName()`只需要一个字符串参数,但是该字符串可以由多个空格隔开的标识符组成,只有当元素的class属性值包含所有指定的标识符时才匹配。 在`Element`类中也同样定义了`getElementsByClassName()`方法,其原理和Document版本是一样的,不过它只选取调用该方法的元素的后代元素。 **1.2.5 通过CSS选择器选取元素** `Document`对象的方法`querySelectorAll()`,它接受一个CSS选择器的字符串参数,返回一个代表文档中匹配选择器的所有元素的NodeList对象,并不是实时的。如果没有匹配的元素,则返回一个空的NodeList对象。 ``` document.querySelectorAll('.div') //匹配所有class名为div的元素 ``` 还有一个`querySelector()`方法,其原理和`querySelectorAll()`是一样的,不过它返回第一个匹配的元素(以文档顺序),如果没有匹配的元素就返回null。 它们支持复杂的CSS选择器。 ``` // 选中data-tip属性等于title的元素 document.querySelectorAll('[data-tip="title"]'); // 选中div元素,那些class含ignore的除外 document.querySelectorAll('div:not(.ignore)'); ``` 但是,它们不支持CSS伪元素的选择器(比如:first-line和:first-letter)和伪类的选择器(比如:link和:visited),即无法选中伪元素和伪类。 这两个方法在`Element`节点上也有定义。 **1.2.6 document.all[ ]** document.all[ ]也可用来选择元素,不过已经废弃了。 ``` document.all[0] //文档中第一个元素 document.all['navbar'] // id或name为“navbar”的元素 ``` **1.3 文档结构和遍历** **1.3.3 作为节点树的文档** `Document`对象、它的`Element对象`和文档中表示文本的Text对象都是Node对象。 Node属性: **(1)parentNode** 该节点的父节点,或者针对类似Document对象应该是null,因为它没有父节点。 **(2)childNodes** 返回只读的类数组对象(NodeList对象),它是该节点的子节点的实时表。 注意:该属性还包括文本节点和评论节点。 **(3)firstChild、lastChild** 该节点的子节点中的第一个和最后一个,如果该节点没有子节点则为null 注意:这两个属性返回的除了HTML元素子节点,还可能是文本节点或评论节点。 **(4)nextSibling、previousSibling** 该节点的兄弟节点中的前一个和下一个。具有相同父节点的两个节点称为兄弟节点。节点的顺序反映了它们在文档中出现的顺序。这两个属性将节点之间以双向链表形式连接起来。 注意:这两个属性返回的除了HTML元素子节点,还可能是文本节点或评论节点。 **(5)textContent** 返回该节点和它的所有后代节点的文本内容。 ```

我是textContent
document.getElementById('div').textContent // 我是textContent ``` **(6)nodeType** 该节点的类型。 9:Document节点 1:Element节点 3:Text节点 8:Comment节点 11:DocumentFragment节点 **(7)nodeValue** Text节点或者Comment节点的文本内容。只有Text节点和Comment节点的nodeValue可以返回结果,其他类型的节点一律返回null。 **(8)nodeName** 元素的标签名,以大写形式表示。 **nodeType和nodeName** ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/dc61fd75984e2ff6ddc9f7146ff35719_532x306.png) 使用这些node属性,我们可以便捷的得到各个节点的引用 ``` document.childNodes[0].childNodes[1] //等价于 document.firstChild.firstChild.nextSibling ``` **1.3.4 作为元素树的文档** 当我们的关注点在文档的元素上而非它们之间的文本上时,JavaScript提供了另外一个API,它将文档看做是E乐门头对象树,忽略部分文档:Text和Comment节点。 **属性** **(1)children** 类似childNodes,返回一个NodeList对象,但children列表只包含Element对象。 **注意**:Text和Comment节点没有children属性,意味着node.parentNode属性不可能返回Text或Comment节点。任何Element的parentNode总是另一个Element,或者,追溯到树根的Document或DocumentFragment节点。 **(2)firstElementChild、lastElementChild** 类似firstChild和lastChild,但只代表`子Element`。 **(3)nextElementSibling、previousElementSibling** 类似nextSibling和previousSibling,但只代表`兄弟Element`。 **(4)childElementCount** 子元素的数量。返回的值和`children.length`值相等。 **(5)offsetParent** offsetParent属性返回当前HTML元素的最靠近的、并且CSS的position属性不等于static的父元素。如果某个元素的所有上层节点都将position属性设为static,则Element.offsetParent属性指向``元素。 **1.4NodeList对象和HTMLCollection对象** **1.4.1 NodeList对象** NodeList实例对象是一个`类数组对象`,它的成员是节点对象。比如node.childNodes、document.querySelectorAll()返回的都是NodeList实例对象。 ``` document.childNodes instanceof NodeList //true ``` NodeList实例对象可能是动态集合,也可能是静态集合。所谓动态集合就是一个活的集合,DOM树删除或新增一个相关节点,都会立刻反映在NodeList接口之中。Node.childNodes返回的,就是一个动态集合。 NodeList接口实例对象提供length属性和数字索引,因此可以像数组那样,使用数字索引取出每个节点,但是它本身并不是数组,不能使用pop或push之类数组特有的方法。 **1.4.2 HTMLCollection对象** HTMLCollection实例对象与NodeList实例对象类似,也是节点的集合,返回类数组对象。 在HTMLDocument类中,有一些快捷属性来访问各种各样的节点。比如:images、forms和links等属性指向类数组的``、``和``(只包含那些有href属性的``标签)元素集合。这些属性都是返回HTMLCollection实例对象。 HTMLDocument也定义了embeds和plugins属性,它们是同义词,都是HTMLCollection类型的``元素的集合。anchors是非标准属性,它指代有一个name属性的``元素。 在HTML5中,加入了scripts,它是HTMLCollection类型的 ';