什么是DOM?
DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作。
DOM1级将HTML和XML文档形象地看作一个层次化的节点树,可以使用JavaScript来操作节点树,进而改变底层文档的外观和结构。
节点层次
DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。
最基本的节点类型是Node,用于抽象地表示文档中一个独立的部分,所有其他类型都继承自Node。
节点类型:
Document
:整个文档树的顶层节点Element
:网页的各种HTML标签Text
:标签之间或标签包含的文本Comment
:注释DocumentType
:doctype
标签Attr
:网页元素的属性
Node类型
每个节点都有一个nodeType属性,用于表示节点的类型。
不同节点的nodeType
属性值和对应的常量如下。
- 元素节点(element):1,对应常量
Node.ELEMENT_NODE
- 属性节点(attr):2,对应常量
Node.ATTRIBUTE_NODE
- 文本节点(text):3,对应常量
Node.TEXT_NODE
- 注释节点(Comment):8,对应常量
Node.COMMENT_NODE
- 文档节点(document):9,对应常量
Node.DOCUMENT_NODE
- 文档类型节点(DocumentType):10,对应常量
Node.DOCUMENT_TYPE_NODE
通过比较常量,可以确定节点的类型
var node = document.documentElement.firstChild;
if(node.nodeType === Node.ELEMENT_NODE{
console.log('该节点是元素节点');
}
nodeName和nodeValue属性
nodeName
属性返回节点的名称nodeValue
属性返回一个字符串,表示当前节点本身的文本值。(文本节点、注释节点、属性节点可以返回结果,其他节点返回null)
<div id="outer">Hello,fanison</div>
var div = document.getElementById('outer')
div.nodeName // 'DIV'
div.nodeValue // null
div.firstChild.nodeValue // 'Hello,fanison'
div是元素节点,nodeValue返回null;div.firstChild是文本节点,所有可以返回文本值
节点关系
文档中所有的节点之间都存在对应的关系,比如可以将body
元素看成是html
元素的子元素,html
元素看成是body
元素的父元素,head
元素可以看成是body
元素的兄弟元素。
每个节点都有一个childNodes
属性,保存一个 NodeList
类数组对象,可通过位置来访问节点(使用方括号或item()方法)
nextSibling
返回紧跟在当前节点后面的第一个同级节点previousSibling
返回当前节点前面的、距离最近的一个同级节点firstChild
返回当前节点的第一个子节点lastChild
返回当前节点的最后一个子节点
<div id="outer"><div id="d1">第1个div</div><div id="d2">第2个div</div><div id="d3">第3个div</div><div id="d4">第4个div</div></div>
var outer = document.getElementById('outer');
var d1 = document.getElementById('d1');
var d2 = document.getElementById('d2');
var d4 = document.getElementById('d4');
d1.nextSibling === d2 // true
d2.previousSibling === d1 // true
outer.firstChild === d1 // true
outer.lastChild === d4 // true
上面代码中,d1.nextSibling
就是紧跟在d1
后面的同级节点d2
d2.previousSibling
就是紧跟在d2
前面的同级节点d1
div
元素的第一个子节点是d1
,最后一个子节点是d4
注意:任意多个的空白符都将导致文本节点的插入,包括一个到多个空格符,换行符,制表符等等. 将显示 ‘#text’,因为在
操作节点
appendChild()
方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点 ```javascript第1个div第2个div第3个div第4个div
var outer = document.getElementById(‘outer’); var p = document.createElement(‘p’); outer.appendChild(p) var d2 = document.getElementById(‘d2’) outer.appendChild(d2)
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1551475/1598153661071-34a4043a-38d1-4b2e-8c38-6dde200930b4.png#align=left&display=inline&height=170&margin=%5Bobject%20Object%5D&name=image.png&originHeight=340&originWidth=1715&size=78774&status=done&style=none&width=857.5)<br />上面代码新建一个`<p>`节点,将其插入`outer`的尾部。<br />插入的是一个已经存在的节点`d2`,结果就是该节点会从原来的位置,移动到`outer`的尾部。
- `insertBefore()`方法接受两个参数(`newNode,referenceNode`),将`newNode`将插在`referenceNode`节点的前面
```javascript
var outer = document.getElementById('outer');
var p = document.createElement('p');
var d1 = document.getElementById('d1')
outer.insertBefore(p,d1)
上面代码新建一个<p>
节点,插在d1
的前面,也就是成为outer
的第一个子节点。
removeChild()
方法接受一个子节点作为参数,用于从当前节点移除该子节点var outer = document.getElementById('outer');
var d1 = document.getElementById('d1');
outer.removeChild(d1);
上面代码移除了d1
节点,这个方法是在d1
的父节点outer
上调用的,不是在d1
上调用的。
replaceChild()
方法接受两个参数(newChild,oldChild
),将一个新的newChild
节点,替换当前oldChild
节点var d1 = document.getElementById('d1')
var newd1 = document.createElement('div');
newd1.textContent = 'New div1';
d1.parentNode.replaceChild(newd1,d1);
上面代码将d1
节点替换成新的newd1
节点
cloneNode()
方法用于克隆一个节点。它接受一个布尔值作为参数,表示是否同时克隆子节点 ```javascript var outer = document.getElementById(‘outer’); var outer2 = outer.cloneNode(false); document.body.appendChild(outer2);
var outer3 = outer.cloneNode(true); document.body.appendChild(outer3);
<a name="r1IWC"></a>
### ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1551475/1598171914297-971d9e0c-9d52-44f6-8805-441bb60997b4.png#align=left&display=inline&height=268&margin=%5Bobject%20Object%5D&name=image.png&originHeight=536&originWidth=1914&size=155155&status=done&style=none&width=957)
`outer2` 节点为浅拷贝,`outer3`节点为深拷贝(克隆子节点)
<a name="sP6nA"></a>
### Document类型
<a name="4uYUt"></a>
#### 特性
- `nodeType` : 9
- `nodeName`: #document
- `nodeValue`: null
- `parentNode`: null
<a name="Dig4l"></a>
#### 文档的子节点
`documentElement`属性返回当前文档的根元素节点(root)
```javascript
var html = document.documentElement;
html === document.childNodes[0];
html === document.firstChild;
documentElement、firstChild、childNodes[0] 都指向元素
文档信息
document.title
属性返回当前文档的标题document.URL
属性返回一个字符串,表示当前文档的网址document.domain
属性返回当前文档的域名,不包含协议和端口document.referrer
属性返回一个字符串,表示当前文档的访问者来自哪里 ```javascript var originalTitle = document.title; document.title = ‘新标题’;
var url = document.URL; var domain = document.domain; var referrer = document.referrer;
<a name="0pvG9"></a>
#### 查找元素
`document.getElementById()`方法返回匹配指定`id`属性的元素节点<br />`document.getElementsByTagName()`方法搜索 HTML 标签名,返回符合条件的元素(返回一个类似数组的的对象)<br />`document.getElementsByName()`方法用于选择拥有`name`属性的 HTML 元素(返回一个类似数组的的对象)
```javascript
<div id="myDiv">Hello,fanison!</div>
var div = document.getElementById('myDiv');
var images = document.getElementByTagName('img'); // 返回当前文档的所有img元素节点
console.log(images.length);
var forms = document.getElementsByName('x');
文档写入
document.open
方法清除当前文档所有内容,使得文档处于可写状态,供document.write
方法写入内容document.close
方法用来关闭document.open()
打开的文档document.write
方法用于向当前文档写入内容document.writeln
方法用于向当前文档写入内容,并在输出内容的尾部添加换行符
Element类型
特性
nodeType
: 1nodeName
: 元素的标签名nodeValue
: nullparentNode
: Document或Element创建元素
document.createElement()
创建新元素var div = document.createElement('div'); // 创建一个 div 元素
取得特性
getAttribute()
返回元素指定的属性值var div = document.getElementById('myDiv');
div.getAttribute('id') // myDiv
设置特性
setAttribute()
接受两个参数:要设置的特性名和值removeAttribute()
删除元素的特性
div.setAttribute('id','newDiv'); // 将id设置为 newDiv
div.removeAttribute('class')
Text类型
特性
nodeType
: 3nodeName
: #textnodeValue
: 节点所包含的文本parentNode
: Element创建文本节点
createTextNode()
接受一个参数,要插入的节点中的文本
以上代码创建了一个新var element = document.createElement('div');
element.className = 'message'
var textNode = document.createTextNode("Hello,fanison!");
element.appendChild(textNode);
document.body.appendChild(element);
<div>
元素并为它指定了值'message'
的class
属性,然后创建文本节点,将文本节点添加到元素中,再将元素添加到body
中。分隔文本节点
splitText()
: 将Text
节点一分为二,变成两个相邻的Text
节点。它的参数就是分割位置(从零开始),分割到该位置的字符前结束 ```javascriptHello,fanison!
var p = document.getElementById(‘p’); var textnode = p.firstChild;
var newText = textnode.splitText(6); newText // “Hello,” textnode // “fanison!”
以上代码将 textnode分隔成两个节点,newText节点为"Hello,",textnode节点为"fanison!"<br />
<a name="FTUjF"></a>
### Comment类型
<a name="k4aYH"></a>
#### 特性
- `nodeType` : 8
- `nodeName`: #comment
- `nodeValue`: 注释的内容
- `parentNode`: Document或Element
<a name="ksQXv"></a>
#### 创建
`createComment()`创建注释节点
```javascript
var comment = document.createComment('A comment');
DocumentType类型
特性
nodeType
: 10nodeName
: doctype的名称nodeValue
: nullparentNode
: Document
DocumentFragment类型
特性
nodeType
: 11nodeName
: #document-fragmentnodeValue
: nullparentNode
: null创建
document.createDocumentFragment() 用于构建一个DOM结构,然后插入当前文档 ```javascript var fragment = document.createDocumentFragment(); // 等同于 var fragment = new DocumentFragment();
var li = document.createElement(‘li’); li.textContent = ‘Hello fanison’; fragment.appendChild(li); document.querySelector(‘ul’).appendChild(fragment);
上面代码创建了一个`DocumentFragment`节点,然后将一个`li`节点添加在它里面,最后将`DocumentFragment`节点移动到原文档。
<a name="1Fbtd"></a>
###
<a name="C1xWK"></a>
### Attr类型
<a name="Bplt1"></a>
#### 特性
- `nodeType` : 2
- `nodeName`: 特性的名称
- `nodeValue`: 特性的值
- `parentNode`: null
<a name="X5QHs"></a>
#### 方法
- createAttribute() 创建并返回一个新的属性节点
```javascript
var attr = document.createAttribute('align');
attr.value = 'left';
element.setAttributeNode(attr)
element.attributes(['align'].value) // 'left'
element.getAttributeNode(['align'].value) // 'left'
element.getAttribute('align') // 'left'
以上代码使用 createAttribute 创建新节点;使用 setAttributeNode将新创建的特性添加到元素中;使用 attributes属性、getAttributeNode()方法、getAttribute()方法可以访问。
CDATASelection类型
已废弃