什么是DOM?
DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作。
DOM1级将HTML和XML文档形象地看作一个层次化的节点树,可以使用JavaScript来操作节点树,进而改变底层文档的外观和结构。

节点层次

DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。
最基本的节点类型是Node,用于抽象地表示文档中一个独立的部分,所有其他类型都继承自Node。

节点类型:

  • Document:整个文档树的顶层节点
  • Element:网页的各种HTML标签
  • Text:标签之间或标签包含的文本
  • Comment:注释
  • DocumentTypedoctype标签
  • 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

通过比较常量,可以确定节点的类型

  1. var node = document.documentElement.firstChild;
  2. if(node.nodeType === Node.ELEMENT_NODE{
  3. console.log('该节点是元素节点');
  4. }

nodeName和nodeValue属性

nodeName属性返回节点的名称
nodeValue属性返回一个字符串,表示当前节点本身的文本值。(文本节点、注释节点、属性节点可以返回结果,其他节点返回null)

  1. <div id="outer">Hello,fanison</div>
  2. var div = document.getElementById('outer')
  3. div.nodeName // 'DIV'
  4. div.nodeValue // null
  5. div.firstChild.nodeValue // 'Hello,fanison'

div是元素节点,nodeValue返回null;div.firstChild是文本节点,所有可以返回文本值

节点关系

文档中所有的节点之间都存在对应的关系,比如可以将body元素看成是html元素的子元素,html元素看成是body元素的父元素,head元素可以看成是body元素的兄弟元素。
每个节点都有一个childNodes属性,保存一个 NodeList类数组对象,可通过位置来访问节点(使用方括号或item()方法)

  • nextSibling返回紧跟在当前节点后面的第一个同级节点
  • previousSibling返回当前节点前面的、距离最近的一个同级节点
  • firstChild返回当前节点的第一个子节点
  • lastChild返回当前节点的最后一个子节点


  1. <div id="outer"><div id="d1">第1div</div><div id="d2">第2个div</div><div id="d3">第3div</div><div id="d4">第4个div</div></div>
  2. var outer = document.getElementById('outer');
  3. var d1 = document.getElementById('d1');
  4. var d2 = document.getElementById('d2');
  5. var d4 = document.getElementById('d4');
  6. d1.nextSibling === d2 // true
  7. d2.previousSibling === d1 // true
  8. outer.firstChild === d1 // true
  9. outer.lastChild === d4 // true

image.png

上面代码中,d1.nextSibling就是紧跟在d1后面的同级节点d2
d2.previousSibling就是紧跟在d2前面的同级节点d1
div元素的第一个子节点是d1,最后一个子节点是d4

注意:任意多个的空白符都将导致文本节点的插入,包括一个到多个空格符,换行符,制表符等等. 将显示 ‘#text’,因为在

标签和
标签之前,有一个换行符和多个空格充当了一个文本节点.

image.png

操作节点

  • 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)

  1. ![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`的尾部。
  2. - `insertBefore()`方法接受两个参数(`newNode,referenceNode`),将`newNode`将插在`referenceNode`节点的前面
  3. ```javascript
  4. var outer = document.getElementById('outer');
  5. var p = document.createElement('p');
  6. var d1 = document.getElementById('d1')
  7. outer.insertBefore(p,d1)

image.png
上面代码新建一个<p>节点,插在d1的前面,也就是成为outer的第一个子节点。

  • removeChild()方法接受一个子节点作为参数,用于从当前节点移除该子节点
    1. var outer = document.getElementById('outer');
    2. var d1 = document.getElementById('d1');
    3. outer.removeChild(d1);
    image.png
    上面代码移除了d1节点,这个方法是在d1的父节点outer上调用的,不是在d1上调用的。
  • replaceChild()方法接受两个参数(newChild,oldChild),将一个新的newChild节点,替换当前oldChild节点
    1. var d1 = document.getElementById('d1')
    2. var newd1 = document.createElement('div');
    3. newd1.textContent = 'New div1';
    4. d1.parentNode.replaceChild(newd1,d1);
    image.png
    上面代码将 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);

  1. <a name="r1IWC"></a>
  2. ### ![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)
  3. `outer2` 节点为浅拷贝,`outer3`节点为深拷贝(克隆子节点)
  4. <a name="sP6nA"></a>
  5. ### Document类型
  6. <a name="4uYUt"></a>
  7. #### 特性
  8. - `nodeType` : 9
  9. - `nodeName`: #document
  10. - `nodeValue`: null
  11. - `parentNode`: null
  12. <a name="Dig4l"></a>
  13. #### 文档的子节点
  14. `documentElement`属性返回当前文档的根元素节点(root)
  15. ```javascript
  16. var html = document.documentElement;
  17. html === document.childNodes[0];
  18. 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;

  1. <a name="0pvG9"></a>
  2. #### 查找元素
  3. `document.getElementById()`方法返回匹配指定`id`属性的元素节点<br />`document.getElementsByTagName()`方法搜索 HTML 标签名,返回符合条件的元素(返回一个类似数组的的对象)<br />`document.getElementsByName()`方法用于选择拥有`name`属性的 HTML 元素(返回一个类似数组的的对象)
  4. ```javascript
  5. <div id="myDiv">Hello,fanison!</div>
  6. var div = document.getElementById('myDiv');
  7. var images = document.getElementByTagName('img'); // 返回当前文档的所有img元素节点
  8. console.log(images.length);
  9. var forms = document.getElementsByName('x');

文档写入

  • document.open方法清除当前文档所有内容,使得文档处于可写状态,供document.write方法写入内容
  • document.close方法用来关闭document.open()打开的文档
  • document.write方法用于向当前文档写入内容
  • document.writeln方法用于向当前文档写入内容,并在输出内容的尾部添加换行符


Element类型

特性

  • nodeType : 1
  • nodeName: 元素的标签名
  • nodeValue: null
  • parentNode: Document或Element

    创建元素

    document.createElement() 创建新元素
    1. var div = document.createElement('div'); // 创建一个 div 元素

    取得特性

    getAttribute()返回元素指定的属性值
    1. var div = document.getElementById('myDiv');
    2. div.getAttribute('id') // myDiv

设置特性

setAttribute()接受两个参数:要设置的特性名和值
removeAttribute()删除元素的特性

  1. div.setAttribute('id','newDiv'); // 将id设置为 newDiv
  2. div.removeAttribute('class')

Text类型

特性

  • nodeType : 3
  • nodeName: #text
  • nodeValue: 节点所包含的文本
  • parentNode: Element

    创建文本节点

    createTextNode() 接受一个参数,要插入的节点中的文本
    1. var element = document.createElement('div');
    2. element.className = 'message'
    3. var textNode = document.createTextNode("Hello,fanison!");
    4. element.appendChild(textNode);
    5. document.body.appendChild(element);
    以上代码创建了一个新<div>元素并为它指定了值 'message'class属性,然后创建文本节点,将文本节点添加到元素中,再将元素添加到body中。

    分隔文本节点

    splitText(): 将Text节点一分为二,变成两个相邻的Text节点。它的参数就是分割位置(从零开始),分割到该位置的字符前结束 ```javascript

    Hello,fanison!

    var p = document.getElementById(‘p’); var textnode = p.firstChild;

var newText = textnode.splitText(6); newText // “Hello,” textnode // “fanison!”

  1. 以上代码将 textnode分隔成两个节点,newText节点为"Hello,"textnode节点为"fanison!"<br />
  2. <a name="FTUjF"></a>
  3. ### Comment类型
  4. <a name="k4aYH"></a>
  5. #### 特性
  6. - `nodeType` : 8
  7. - `nodeName`: #comment
  8. - `nodeValue`: 注释的内容
  9. - `parentNode`: DocumentElement
  10. <a name="ksQXv"></a>
  11. #### 创建
  12. `createComment()`创建注释节点
  13. ```javascript
  14. var comment = document.createComment('A comment');

DocumentType类型

特性

  • nodeType : 10
  • nodeName: doctype的名称
  • nodeValue: null
  • parentNode: Document

DocumentFragment类型

特性

  • nodeType : 11
  • nodeName: #document-fragment
  • nodeValue: null
  • parentNode: 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);

  1. 上面代码创建了一个`DocumentFragment`节点,然后将一个`li`节点添加在它里面,最后将`DocumentFragment`节点移动到原文档。
  2. <a name="1Fbtd"></a>
  3. ###
  4. <a name="C1xWK"></a>
  5. ### Attr类型
  6. <a name="Bplt1"></a>
  7. #### 特性
  8. - `nodeType` : 2
  9. - `nodeName`: 特性的名称
  10. - `nodeValue`: 特性的值
  11. - `parentNode`: null
  12. <a name="X5QHs"></a>
  13. #### 方法
  14. - createAttribute() 创建并返回一个新的属性节点
  15. ```javascript
  16. var attr = document.createAttribute('align');
  17. attr.value = 'left';
  18. element.setAttributeNode(attr)
  19. element.attributes(['align'].value) // 'left'
  20. element.getAttributeNode(['align'].value) // 'left'
  21. element.getAttribute('align') // 'left'

以上代码使用 createAttribute 创建新节点;使用 setAttributeNode将新创建的特性添加到元素中;使用 attributes属性、getAttributeNode()方法、getAttribute()方法可以访问。

CDATASelection类型

已废弃