DOM(文档对象模型)是针对 HTML 或 XML 文档的一个 API,它描绘了一个层次化的节点数,允许开发人员添加、移除、修改页面的某一部分。
节点层次
- DOM 将 HTML 或 XML 文档描绘成一个由多次层节点构成的结构
- 节点由不同类型,每种类型分别表示文档中不同的信息或标记;每个节点都有各种的特点、数据、方法,并与其他节点存在某种关系。
- 节点之间的关系构成了层次,所有页面标记表现为一个以特定节点为根节点的树形结构
- 文档节点 是每个文档的根节点。每个文档只要一个文档元素,在 HTML 中,文档元素始终是
<html>
元素
Node 类型
- DOM 中定义一个 Node 接口,该接口由 DOM 中所有节点类型实现。
- JavaScript 中所有节点类型(12 种)都继承自 Node 类型
Node 属性
Node.nodeType
, 返回该节点类型所有对应的数值常量(12 种)Node.nameName
, 返回包含该节点名字的DOMString
。HTMLElement
节点的对应元素的标签名(),Text
节点 对应的是"#text"
,Document
节点对应的是"#document"
.Node.nodeValue
,返回或设置当前节点的值Node.childNodes
,返回该节点的所有子节点的实时的NodeLis
.即 NodeList 是动态变化的,如果该节点的子节点发生变化,NodeList 对象会自动更新Node.parentNode
,返回该节点的父节点Node
,没有则为null
Node.firstChild
,返回该节点的第一个子节点Node
,没有则为null
Node.lastChild
,返回该节点的最后一个子节点Node
,没有则为null
Node.nextSibling
,返回该节点同辈的下一个节点Node
,没有则为null
Node.previousSibling
,返回该节点同辈的前一个节点Node
,没有则为null
Node.ownerDocument
,返回该节点属于的Document
对象。如果没有与之关联的Document
对象,则返回null
Node.isConnected
,检测该节点是否已经连接到一个上下文对象,可用来判断一个节点是否已插入文档中
另外,还有一组与之类似的新属性,是只考虑文档中的HTMLElment
类型节点,忽略Text
节点。Node.children
,Node.childElementCount
,Node.firstElementChild
,Node.lastElementChild
,Node.parentElement
,Node.nextElementSibling
,Node.previousElementSibling
Node 方法
Node.appendChild(child)
,将指定节点作为最后一个子节点添加到当前节点。不能跨文档插入,只能将某个节点插入到同一文档的其他位置Node.insertBefore(newNode,referenceNode)
,在参考节点之前插入一个子节点。- 如果要插入的节点是对文档中现有节点的引用,那么
insertBefore()
会将其从当前位置移动到新的位置。这意味着,一个节点不能同时位于文档的两个位置。 - 如果插入节点在选用文档中,可使用
Node.cloneNode()
复制该节点,但需要注意,该节点 副本不会自动同原始节点保持同步 - 如果引用节点
null
,则指定节点添加到父节点末尾。 - 如果给定的子节点是
DocumentFragment
,那么其全部内容将被移动到父节点的子节点列表中
- 如果要插入的节点是对文档中现有节点的引用,那么
Node.removeChild(child)
,移除当前节点的指定子节点,并返回移除的节点。如果参数引用了 DOM 树上现有的节点,则节点从当前位置分离,并添加到新位置Node.repalceChild(newChild,oldChild)
,用指定节点替换当前节点的一个子节点。并返回被替换掉的节点。Node.cloneNode(deep)
,克隆一个节点,参数deep
可选,是否参数深度克隆,为true
,则该节点的所有后代节点也会被克隆,false
,则只会克隆该节点本身。- 克隆一个元素节点会拷贝它所有的属性以及属性值。所有属性上绑定的事件会被拷贝(例如
node.onclick="alert(123)"
)。但是不会拷贝使用addEvntListener()
方法或者`node.onclick=”fn”这种动态绑定的事件 - 如果元素节点设置了
id
属性,并且克隆节点要插入相同的文档中,那么应该更改克隆节点的id
属性,以保持唯一性。name
属性可能也需要进行修改。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27<body>
<div id="box">
<p onclick="alert(123)">nihao</p>
<p>天天向上</p>
</div>
<script>
function sayHello() {
alert("hello");
}
var box = document.getElementById("box");
var p2 = box.lastElementChild;
p2.onclick = sayHello;
let clone = box.cloneNode();
clone.setAttribute("id", "clone");
let deepClone = box.cloneNode(true);
deepClone.setAttribute("id", "deepClone");
console.log(
"clone: %o, deepClone: %o",
clone.childNodes,
deepClone.childNodes
);
box.parentNode.appendChild(clone);
box.parentNode.appendChild(deepClone);
</script>
</body>- 克隆一个元素节点会拷贝它所有的属性以及属性值。所有属性上绑定的事件会被拷贝(例如
Node.getRootNode()
,返回上下文对象的根节点Node.hasChildNodes()
,该节点是否包含子节点Node.contains(otherNode)
,传入节点是否为该节点的后代节点.**如果插入节点是该节点本身,则也返回 ture. (例如document.body.contains(document.body)
,返回 true) **Node.isEqualNode()
,判断两个节点是否相同。两节点类型相同,且属性、属性值,节点值相同,则返回 true。
Documnet 类型
JavaScript 通过 Document 类型表示文档,它是HTMLDocument
的一个实例。在浏览器中,document
对象表示整个 HTML 页面,是 window 对象的一个属性,因此可以将其作为全局对象来访问。通过该document
对象,不仅可以取得与页面相关的信息,而且还能操作页面的外观以及其底层结构。
文档子元素
Document.documentElement
,返回当前文档的直接子节点,在 HTML 文档中,指向 HTML 页面的<html>
元素Document.body
,指向<body>
元素
文档信息
Document.doctype
,返回文档类型定义Document.characterSet
,返回当前文档的字符编码Document.title
,获取或设置文档的标题Document.cookie
,返回一个使用分号分隔的 cookie 列表,或设置一个 cookieDocument.location
,返回当前文档的Location
对象。
查找元素
getElementById()
,返回一个Element
元素getElementTagName()
,返回元素的 HTML 集合HTMLCollection
querySelector()
m 根据 css 选择器匹配,返回匹配的第一个Element
元素querySelectorAll()
, 返回一个节点集合NodeList
HTMLCollection 和 NodeList
NodeList
是一个节点的集合,由Node.chidNodes
和documet.querySelectorAll()
返回的。有item()
,entries()
,keys()
,values()
方法
- 一些情况下,
NodeList
是一个实时集合,例如Node.childNodes
是实时的 - 在其他情况下,
NodeList
是一个静态集合,例如,querySelectorAll()
返回的是一个静态NodeList
.
HTMLCollection
是一个包含了 html 元素的集合,由getElementByTagName()
返回的,它是即时更新的(live),当其所包含的文档结构发生改变时,它会自动更新。有item()
,namedItem()
方法
特殊结合
Document.all
,返回一个以文档节点为根节点的HTMLAllCollection
集合Document.forms
,返回当前 文档中所有表单元素<form>
的HTMLCollection
列表Document.images
,返回当前文档中所有图片元素<img>
的HTMLCollection
列表Document.links
,返回当前文档中所有超链接元素<a>
的HTMLCollection
列表
Element 类型
Element 类型通常用于表现 THML 或 XML 元素,这个接口描述了所有相同类型元素所具有的方法和属性。一些接口继承自Element
并增加了一些额外功能,例如,HTMLElement
接口是所有 HTML 元素的基本接口。
元素特性信息
Element.id
,该元素的 id 属性值Element.tagName
,该元素标签名,同Node.nodeName
值相同.注意,标签名以全部大写表示Element.className
,该元素的 class 属性的值Element.classList
,该元素包含的 calss 属性,是一个DOMTokenList
Element.attributes
,与该元素相关的所有属性的集合NamedNodeMap
Element.innerHTML
,元素的内容
获取/设置特性
getAttribute(name)
,返回元素上一个指定的属性值,如果不存在,返回null
style
特性,其属性值和通过getAttribute()
返回的值不同,前者返回一个对象CSSStyleDeclaration
,后者返回 style 特性值中包含 CSS 文本onclicke
特性,属性值返回一个 JavaScript 函数 ,getAttribute()
返回相应代码的字符串
setAttribute(name, value)
,设置元素上的某个属性值,如果属性已存在,则更新该值。removeAttribute(name)
,从元素 中删除指定属性。
classList 属性
元素的classList
属性是一个DOMTokenList
集合,此类型定义了以下方法:
add(value)
,将指定字符串值添加到列表,如果已存在,则忽略remove(value)
,从列表删除给定的字符串toggle(value)
,如果列表中已存在给定的值,删除它。如果不存在,添加它。contains(value)
,列表中是否存在给定的值
attrubutes 属性
Element.attributes
,返回与该元素相关的所有属性的实时集合NamedNodeMap
。NamedNodeMap
接口表示属性节点Attr
对象的集合,它也是即时的(live),如果它内部包含的对象发生改变,该对象会自动更新。
元素尺寸/位置信息
Element.clientHeight
,Element.clientWidth
,元素内部像素高度/宽度(包含内边距,但不包括滚动条,边框和外边距)Element.offsetHeight
,Element.offsetWidth
,元素像素高度/宽度,包含元素的内边距,边框,和滚动条(chrome 17px)Element.scrollHeight
,Element.scrollWidth
,元素的滚动视图高度/宽度,包括由于溢出导致的不可见内容。- 在没有滚动条情况下,同
clientHeight
,clientWidth
值相同 scrollHeight
也包括::before
和::after
伪元素
- 在没有滚动条情况下,同
Element.scrollTop
,Element.scrollLeft
,元素纵向/横向滚动条位置(即超出可视区域的内容大写)纵向滚动条最底层滚动条位置:scrollTop = scrollHeight - clientHeight
创建元素
document.createElement(tagName)
,创建一个由标签名称指定的 HTML 元素document.createTextNode()
,创建一个新的文本节点document.createAttribute()
,创建并返回一个新的属性节点
insertAdjacentHTML()
element.insertAdjacentHTML(position,text)
,将指定的文本,解析为 Element 元素,并将结果节点插入到 DOM 树种的给定位置。参数position
表示插入内容相对于元素的位置。
"beforbegin"
,插入到元素自身的前面"afterbegin"
,插入到元素内部的第一个子节点之前"beforeend"
,插入到元素内部的最后一个子节点之后"afterend"
,元素自身的后面
1 | <!-- beforebegin --> |
Text 类型
文本节点由 Text 类型表示,可以包含转义后的 HTML 字符,但不能包含 HTML 代码。
操作文本节点
appendData(text)
,添加文本到节点末尾deleteData(offset, count)
,从 offset 指定位置开始删除 count 个字符insertData(offset,text)
,在 offset 位置插入文本replaceDate(offset,count,text)
,用 text 替换从 offset 指定位置开始到offset+count
为止处的文本splitText(offset)
,从 offset 处将文本分成 2 个文本节点substringData(offset,count)
,提取从 offset 位置到offset + count
为止处的字符串normalize()
,规范文本节点,在包含 2 个或多个文本节点的父元素上调用,会将所有文本节点合并成一个节点
DocumentFragment 类型
文档片段是一种“轻量级”的文档,可以包含、控制节点,但不会像完整的文档那些占用额外资源。虽然不能将文档片段直接添加到文档,但可以将它当作一个“仓库”开使用,在里面保存将来可能要添加到文档的节点。
- 文档片段继承了
Node
所有方法 - 在 将文档片段添加文档时,实际上只会将文档片段所有的子节点添加到文档相应的位置,此时文档片段中的所有子节点都被删除。
Attr 类型
元素的特性在 DOM 中以 Attr 类型表示。
- 元素的
attributes
属性中节点,即使特性节点 - 尽管其也是节点,但特性却不认为是 DOM 文档树的部分。
方便的表格操作
为了方便构建表格,HTMLDOM 还为<table>
,<tbody>
,<tr>
元素提供了一些特殊的属性和方法.
table 元素
caption
,对<caption>
元素的指针tFoot
,对<tfoot>
元素的指针tHead
,对<thead>
元素是指针tBodies
,<tbody>
元素的 HTMLCollectionrows
,表格所有行的 HTMLCOllectioncreateTHead()
,deleteTHead()
,创建/删除<thead>
元素createTFoot
,deleteTFoot()
,创建/删除<tfoot>
元素insetRow(pos)
,像 rows 集合中的指定位置插入一行deleteRow(pos)
,删除指定位置的行tbody 元素
rows
,<tbody>
元素 中所有行的 HTMLCollectioninsertRow(pos)
,deleteRow(pos)
,在<tbody>
元素中,向 rows 集合中插入/删除指定 位置的一行
tr 元素
cells
,<tr>
元素单元格的 HTMLCollectioninsertCell(pos)
,deleteCell()
,向 cells 集合中,插入/删除指定的一个单元格
DOM 对性能的影响
NodeList
对象是“动态的”,这意味中每次访问NodeList
对象,都会运行一次基于文档的查询,因此,要尽量减少 DOM 操作- 文档中每一次的添加(
appendChild()
)或插入(insertBefore()
)节点,都会触发 DOM 树的重新渲染。可先在文档片段(document fragment)中处理好后,在一次性的插入到文档中,这种操作仅发生一次重新渲染。