目录
14.3.2 MutationObserverInit与观察范围
文档对象模型(DOM, Document Object Model)是HTML和XML文档的编程接口。DOM表示由多层节点构成的文档,通过它开发者可以添加、删除和修改页面的各个部分。DOM现在是真正跨平台、语言无关的表示和操作网页的方式。
14.1 节点层级
根节点的唯一子节点是<html>元素,我们称之为文档元素(documentElement)。文档元素是文档最外层的元素,所有其他元素都存在于这个元素之内。每个文档只能有一个文档元素。
14.1.1 Node类型
(1)nodeName与nodeValue保存着有关节点的信息。
(2)节点关系
(3)appendChild()方法用于在childNodes列表末尾添加节点;insertBefore()方法把节点放到childNodes中的特定位置而不是末尾;replaceChild()方法要替换的节点会被返回并从文档树中完全移除,要插入的节点会取而代之;removeChild()方法要移除节点而不是替换节点。
(4)其他方法
- 第一个是cloneNode(),会返回与调用它的节点一模一样的节点。cloneNode()方法接收一个布尔值参数,表示是否深复制。
- normalize()。这个方法唯一的任务就是处理文档子树中的文本节点。
14.1.2 Document类型
Document类型是JavaScript中表示文档节点的类型。
(1)提供了两个访问子节点的快捷方式
- 第一个是documentElement属性,始终指向HTML页面中的<html>元素。
- Document类型另一种可能的子节点是DocumentType。
(2)文档信息:ducument.title、ducument.URL、ducument.domain、ducument.referrer
(3)定位元素:getElementById()和getElementsByTagName()就是Document类型提供的两个方法。
(4)特殊集合:document.anchors、 document.applets、document.forms、document.images、document.links
(5)略
(6)向网页输出流中写入内容。对应4个方法:write()、writeln()、open()和close()。
14.1.3 Element类型
Element表示XML或HTML元素,对外暴露出访问元素标签名、子节点和属性的能力。
(1)所有HTML元素都通过HTMLElement类型表示,包括其直接实例和间接实例。
- id,元素在文档中的唯一标识符;
- title,包含元素的额外信息,通常以提示条形式展示;
- lang,元素内容的语言代码(很少用);
- dir,语言的书写方向("ltr"表示从左到右,"rtl"表示从右到左,同样很少用);
- className,相当于class属性,用于指定元素的CSS类(因为class是ECMAScript关键字,所以不能直接用这个名字)。
(2)取得属性:getAttribute()、setAttribute()和removeAttribute()。这些方法主要用于操纵属性,包括在HTMLElement类型上定义的属性。
(3)设置属性:setAttribute(),这个方法接收两个参数:要设置的属性名和属性的值。
(4)Element类型是唯一使用attributes属性的DOM节点类型。
(5)可以使用document.createElement()方法创建新元素。
(6)元素后代:childNodes属性包含元素所有的子节点,这些子节点可能是其他元素、文本节点、注释或处理指令。
14.1.4 Text类型
Text节点由Text类型表示,包含按字面解释的纯文本,也可能包含转义后的HTML字符,但不含HTML代码。
(1)创建文本节点
document.createTextNode()可以用来创建新文本节点,它接收一个参数,即要插入节点的文本。(2)规范化文本节点
DOM文档中也经常会出现两个相邻文本节点。为此,有一个方法可以合并相邻的文本节点。这个方法叫normalize(),
(3)拆分节点
DOM文档中也经常会出现两个相邻文本节点。为此,有一个方法可以合并相邻的文本节点。这个方法叫normalize()。
14.1.5 Comment类型
Comment类型与Text类型继承同一个基类(CharacterData),因此拥有除splitText()之外Text节点所有的字符串操作方法。
14.1.6 CDATASection类型
CDATASection类型继承Text类型,因此拥有包括splitText()在内的所有字符串操作方法。
14.1.7 DocumentType类型
略
14.1.8 DocumentFragment类型
略
14.1.9 Attr类型
很少用,略
14.2 DOM编程
14.2.1 动态脚本
有两种方式通过<script>动态为网页添加脚本:引入外部文件和直接插入源代码。
14.2.2 动态样式
CSS样式在HTML页面中可以通过两个元素加载。<link>元素用于包含CSS外部文件,而<style>元素用于添加嵌入样式。
14.2.3 操作表格
通过DOM编程创建<table>元素
14.2.4 使用NodeList
理解NodeList对象和相关的NamedNodeMap、HTMLCollection,是理解DOM编程的关键。
14.3 MutationObserver接口
使用MutationObserver可以观察整个文档、DOM树的一部分,或某个元素。此外还可以观察元素属性、子节点、文本,或者前三者任意组合的变化。
14.3.1 基本用法
(1)observe()方法
新创建的MutationObserver实例observer与DOM关联起来,需要使用observe()方法。接收两个必需的参数:要观察其变化的DOM节点,以及一个MutationObserverInit对象。
(2)回调与MutationRecord
每个回调都会收到一个MutationRecord实例的数组。MutationRecord实例包含的信息包括发生了什么变化,以及DOM的哪一部分受到了影响。
(3)disconnect()方法
要提前终止执行回调,可以调用disconnect()方法。
(4)复用MutationObserver
多次调用observe()方法,可以复用一个MutationObserver对象观察多个不同的目标节点。
(5)重用MutationObserver
调用disconnect()并不会结束MutationObserver的生命。还可以重新使用这个观察者,再将它关联到新的目标节点。
14.3.2 MutationObserverInit与观察范围
MutationObserverInit对象用于控制对目标节点的观察范围。
(1)观察属性
MutationObserver可以观察节点属性的添加、移除和修改。
(2)观察字符数据
MutationObserver可以观察文本节点(如Text、Comment或ProcessingInstruction节点)中字符的添加、删除和修改。
(3)观察子节点
MutationObserver可以观察目标节点子节点的添加和移除。要观察子节点,需要在Mutation-ObserverInit对象中将childList属性设置为true。
(4)观察子树
MutationObserver将观察的范围限定为一个元素及其子节点的变化。可以把观察的范围扩展到这个元素的子树(所有后代节点),这需要在MutationObserverInit对象中将subtree属性设置为true。
14.3.3 异步回调与记录队列
为了在大量变化事件发生时不影响性能,每次变化的信息(由观察者实例决定)会保存在MutationRecord实例中,然后添加到记录队列。
(1)记录队列
(2)调用MutationObserver实例的takeRecords()方法可以清空记录队列,取出并返回其中的所有MutationRecord实例。
14.3.4 性能、内存与垃圾回收
无论如何,使用MutationObserver仍然不是没有代价的。
(1)MutationObserver的引用
(2)MutationRecord的引用
14.4 小结
- 要理解DOM,最关键的一点是知道影响其性能的问题所在。
- DOM操作在JavaScript代码中是代价比较高的,NodeList对象尤其需要注意。NodeList对象是“实时更新”的,这意味着每次访问它都会执行一次新的查询。考虑到这些问题,实践中要尽量减少DOM操作的数量。