JavaScript红宝书10-文件 对象 模型(The Document Object Model DOM)

61 阅读5分钟

The Document Object Model (DOM) 是HTML文件的接口,DOM将文件表示为节点的分层树形结构,开发者可以添加、删除和修改页面的各个部分。

节点的层级

所有的HTML文件都可以使用DOM表示为有层级的节点,文件中的多种节点类型,表示不同的信息,不同类型的节点有不同的,字符、数据、方法以及和其他的节点的关系,这些关系会形成一个树型结构。

举个栗子,最基础的一段HTML

<html lang="en">
  <head>
    <title>Document</title>
  </head>
  <body>
    <p>ha ha ha</p>
  </body>
</html>

document节点代表每个文件的根节点,在这个例子中,只有一个子节点元素,document是最外层元素,所有其他元素都在这里,每个文件都只能有一个document元素。

每段标记代表树中一个节点,元素节点代表HTML元素,节点属性代表HTML元素属性,共计有12种类型的节点,都继承自一种基础类型。

节点类型

DOM 的第一级 描述了名为Node的接口,用来实现DOM中所有节点,这个Node接口被JavaScript作为Node类型实现,所有的节点都继承自Node类型,共享Node类型的基本属性与方法。

每一个节点都有nodeType属性,节点有这12种类型:

Node.ELEMENT_NODE (1) 元素

Node.ATTRIBUTE_NODE (2) 属性

Node.TEXT_NODE (3) 文本

Node.CDATA_SECTION_NODE (4) 数据

Node.ENTITY_REFERENCE_NODE (5) 实体引用

Node.ENTITY_NODE (6) 实体

Node.PROCESSING_INSTRUCTION_NODE (7)

Node.COMMENT_NODE (8) 注释

Node.DOCUMENT_NODE (9) 文件

Node.DOCUMENT_TYPE_NODE (10) 文件类型

Node.DOCUMENT_FRAGMENT_NODE (11) 组件

Node.NOTATION_NODE (12)

节点间的关系

在文件中的所有节点,都与其他节点有关系,这些关系可以描述出一颗家族树。在一个HTML文件中元素是元素的子元素,元素与元素是兄弟元素。

每个节点都有个存储子节点的属性——childNodes,里面包含一个NodeList,类似于数组结构,切记,不是数组,即使可以通过中括号加下标访问元素,那也不是数组。

节点关系图

这种关系使节点访问起来会非常方便,在文件树中,通过关系指针就可以找到每一个节点。

节点操作

由于所有节点的关系指针都是只读的,操作节点需要通过指定的方法,其中最常用的是appendChild()方法,在nodeList末尾添加子节点,如果appendChild()传入的节点已经是文档的一部分,那么会把之前的那部分挪到新的位置。

如果需要插入节点到指定位置可以调用insertBefore()方法

注意:这两个方法都不会删除任何节点,只是有可能移动其他节点的位置。

其他方法

移除:removeChild(),传递一个参数指定要移除的节点,方法的返回值是移除的那个节点。

复制:cloneChild(),接收一个布尔类型参数确定是深复制还是浅复制,深复制,复制节点和所有子树。浅复制,只复制初始节点。

Document类型

在JavaScript中Document代表文件类型,是HTMLDocument的实例,代表所有的HTML页,document是window的属性,window是全局可访问的,所以document也是全局可访问的,document包含以下信息:

nodeType:9

nodeName:#document

nodeValue:null

parentNode:null

ownerDocument:null

查找元素位置

最常用的获取元素引用,Document类型提供了两种方法,getElementById()和getElementByTagName()

getElementById()方法,接收一个参数,元素ID,通过ID获取元素,找不到出现null,ID参数必须完全匹配。

注意:如果同一个ID在相同页面出现多次,那么getElementById()方法只会返回第一次出现这个ID的元素

getElementByTagName()会返回一个nodeList,里面可能会包含0个或多个节点。

Element类型

Element类型是web开发中最常用的类型,代表HTML文件中的元素,Element类型主要包括信息

nodeType:1

nodeName:元素的tag name

nodeValue:null

parentNode:Document或者Element

tag name通常是把元素标签转为大写,如:div转为DIV

HTML元素

所有HTML元素都是HTMLElement类型,HTMLElement直接继承自Element类型,再添加自己的属性。

属性 attribute

属性有三种基本操作方法,get、set和remove,读取、设置和移除

getAttribute("name")

setAttribute("name", "value")

removeAttribute("name")

attribute属性中包含一个NamedNodeMap是一个动态的集合,类似于NodeList,由于是Map这种结构,可以简写为如下形式获取属性 element.attributes["id"].nodeValue。

创建元素

创建元素可通过document.createElement()方法创建,只接收一个参数tag name,通过createElement()方法创建的元素可以设置所属文件属性。

Text类型

Text节点是Text类型,包括普通文本和除了HTML代码外的字符,主要包含以下信息:

nodeType:3

nodeName:#text

nodeValue:文本节点包含的文本

parentNode:Element类型

没有子节点

创建Text节点

创建Text节点可通过document.createTextNode()方法创建节点,接收一个参数文本插入到节点。

Mutation Observer(动态观察者)

MutationObserver API 相对较新添加的DOM规范,允许修改DOM时异步执行回调方法,使用MutationObserver可以观察整个文件,或者一个DOM子树,或者一个元素,除此之外还可以观察:元素属性、子节点和文本。

基本使用

创建

通过构造函数创建,参数传递一个回调函数,如下

let muObserver = new MutationObserver(() => {
  console.log('<body> was changed');
})

observe()方法

之前那个实例与DOM没有任何联系,通过observe()方法进行建立连接,使用如下

muObserver.observe(document.body, {attributes: true})

当修改body后,MutationObserver构造函数中的回调函数会执行

document.body.title = 'good'