JS里的DOM

发布 : 2019-11-11 分类 : JavaScript 浏览 :

1、基本概念

1.1 DOM

DOM全称为文档对象模型(Document Object Model)。

作用:将网页转为一个JavaScript对象,从而可以用脚本进行各种操作。

1.2 节点

DOM的最小组成单位叫节点(node)。

节点的七种类型如下:

  • Document:整个文档树的顶层节点
  • DocumentType:doctype标签
  • Element:网页的各种HTML标签
  • Attribute:网页元素的属性
  • Text:标签之间或标签包含的文本
  • Comment:注释
  • DocumentFragment:文档的片段

浏览器提供一个原生的节点对象Node,以上的七种节点都继承了Node,因此具有一些共同的属性和方法。

1.3 节点树

一个文档的所有节点,按照所在层级,可以抽象成一种树状结构,这种树状结构就叫DOM树。

浏览器提供原生的document节点,代表整个文档。
document

从上图可以看出,文档的第一层只有一个节点,就是HTML网页的第一个标签<html>,它构成了树结构的根节点(root node),其他HTML标签节点都是它的下级节点。

除了根节点,其他节点都具有三种层级关系:

  • 父节点关系(parentNode):直接的上级节点
  • 子节点关系(childNode):直接的下级节点
  • 同级节点关系(sibling):拥有同一个父节点的节点

2、Node接口的属性

所有DOM节点都继承了Node接口,拥有一些共同的属性和方法。

2.1 Node.nodeType

该属性返回一个整数值,表示节点的类型。

nodeType属性可以用来区分不同类型的节点。

不同节点的nodeType属性值和对应常量如下:

节点类型 属性值 常量
元素节点(element) 1 Node.ELEMENT_NODE
文本节点(text) 3 Node.TEXT_NODE
注释节点(Comment) 8 Node.COMMENT_NODE
文档节点(document) 9 Node.DOCUMENT_NODE
文档类型节点(DocumentType) 10 Node.DOCUMENT_TYPE_NODE
文档片断节点(DocumentFragment) 11 Node.DOCUMENT_FRAGMENT_NODE

2.2 Node.nodeName

该属性返回节点的名称。

不同节点的nodeName属性值如下:

  • 文档节点(document):#document
  • 元素节点(element):大写的标签名
  • 属性节点(attr):属性的名称
  • 文本节点(text):#text
  • 文档片段节点(DocumentFragment):#document-fragment
  • 文档类型节点(DocumentType):文档的类型
  • 注释节点(Comment):#comment

2.3 Node.nodeValue

该属性返回一个字符串,表示当前节点本身的文本值。
只有文本节点(text)和注释节点(comment)有文本值,因此这两类节点的nodeValue可以返回结果并设置属性的值,其他类型的节点都将返回null且设置属性的值无效。

1
<div id="div">div</div>

1
2
3
var div = document.getElementById('div')
console.log(div.nodeValue) //null
console.log(div.firstChild.nodeValue) //div

2.4 Node.textContent

该属性返回当前节点和它的所有后代节点的文本内容。

textContent属性自动忽略当前节点内部的HTML标签,返回所有文本内容。

在设置该属性的值时,如果内容有标签,将不会当作标签处理,将解释为文本。

如果要读取整个文档的内容,可以使用document.documentElement.textContent。

与innerText的区别:

  • textContent会获取所有元素内容,包括<script>和<style>元素,而innerText不会。
  • innerText不会返回隐藏元素的文本(display:none;),但textContent会返回隐藏元素的文本。
  • 由于innerText受CSS样式影响,它会触发重排(reflow),但textContent不会触发重排。

2.5 Node.baseURI

该属性返回一个字符串,表示当前网页的绝对路径。

如果无法读取到网页URL,将返回null。

该属性的值一般由window.location属性决定,可以使用HTML的<base>标签改变属性的值。

2.6 Node.nextSibling

该属性返回紧跟在当前节点后面的第一个同级节点,如果当前节点后面没有同级节点,将返回null。

nextSibling属性可以用来遍历所有子节点。

注意:该属性还包括文本节点和注释节点。因此如果当前节点后面有空格,该属性就会返回一个文本节点,内容为空格!

2.7 Node.previousSibling

该属性返回当前节点前面的、距离最近的一个同级节点,如果当前节点前面没有同级节点,将返回null。

注意:该属性还包括文本节点和注释节点。因此如果当前节点前面有空格,该属性就会返回一个文本节点,内容为空格

2.8 Node.parentNode

该属性返回当前节点的父节点。

对一个节点来说,它的父节点只可能是三种类型:元素节点(element)、文档节点(document)、文档片段节点(documentfragment)。

2.9 Node.parentElement

该属性返回当前节点的父元素节点。如果当前节点没有父节点,或者父节点类型不是元素节点,返回null。

2.10 Node.firstChild

该属性返回当前节点的第一个子节点,如果当前节点没有子节点,返回null。

注意:firstChild返回的除了元素节点,还可能是文本节点或者注释节点

2.11 Node.lastChild

该属性返回当前节点的最后一个子节点,如果当前节点没有子节点,返回null,用法跟firstChild一样。

2.12 Node.childNodes

该属性返回一个类似数组的对象(NodeList列表),成员包括当前节点的所有子节点。

注意:返回值也包括文本节点和注释节点

childNodes
从上图可以看出:childNodes是获取子节点并包括了文本节点,而children是获取子标签(没有包括文本节点)。

3、Node接口的方法

3.1 Node.appendChild()

该方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点。该方法的返回值就是插入文档的子节点。

1
2
3
// 创建一个新的段落p元素,然后添加到body的最尾部
var p = document.createElement("p");
document.body.appendChild(p);

3.2 Node.cloneNode()

该方法用于克隆一个节点,它接受一个布尔值作为参数,表示是否同时克隆子节点,它的返回值是一个克隆出来的新节点。

参数为true表示采用深度克隆,为false或者不填表示采用浅克隆。

1
2
3
<div id="div">
拷贝
</div>
1
2
3
#div{
border: 1px solid red;
}
1
2
var div1 = div.cloneNode()
document.body.appendChild(div1)

从以上代码可以得到:
如果var div1 = div.cloneNode()将是浅拷贝,只将克隆该节点本身。
如果var div1 = div.cloneNode(true)将是深拷贝,该节点的所有后代节点也都会被克隆。

3.3 Node.contains()

该方法返回一个布尔值,表示参数节点是否满足以下三个条件之一

  • 参数节点为当前节点
  • 参数节点为当前节点的子节点
  • 参数节点为当前节点的后代节点

3.4 Node.hasChildNodes()

该方法返回一个布尔值,表示当前节点是否有子节点。

注意:子节点包括所有节点,哪怕节点只包括一个空格,该方法也会返回true

判断一个节点是否有子节点的三种方法:

  • node.hasChildNodes()
  • node.firstChild !== null
  • node.childNodes && node.childNodes.length > 0

3.5 Node.insertBefore()

该方法用于将某个节点插入父节点内部的指定位置。

1
var insertedNode = parentNode.insertBefore(newNode, referenceNode);

insertBefore方法接受两个参数,第一个参数是所要插入的节点newNode,第二个参数是父节点parentNode内部的一个子节点referenceNode。newNode将插在referenceNode这个子节点的前面。返回值是插入的新节点newNode。

如果insertBefore方法的第二个参数为null,则新节点将插在当前节点内部的最后位置,即变成最后一个子节点。

3.6 Node.removeChild()

该方法接受一个子节点作为参数,用于从当前节点移除该子节点。返回值是移除的子节点。

注意:被移除的节点依然存在于内存之中,但不再是 DOM 的一部分。所以,一个节点移除以后,依然可以使用它,比如插入到另一个节点下面。

3.7 Node.replaceChild()

该方法用于将一个新的节点,替换当前节点的某一个子节点。

1
var replacedNode = parentNode.replaceChild(newChild, oldChild);

replaceChild方法接受两个参数,第一个参数newChild是用来替换的新节点,第二个参数oldChild是将要替换走的子节点。返回值是替换走的那个节点oldChild。

3.8 Node.isEqualNode()

该方法返回一个布尔值,用于检查两个节点是否相等。所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同。

1
2
3
4
var p1 = document.createElement('p');
var p2 = document.createElement('p');

p1.isEqualNode(p2) // true

3.9 Node.isSameNode()

该方法返回一个布尔值,表示两个节点是否为同一个节点。

1
2
3
4
5
var p1 = document.createElement('p');
var p2 = document.createElement('p');

p1.isSameNode(p2) // false
p1.isSameNode(p1) // true

3.10 Node.normalize

该方法用于清理当前节点内部的所有文本节点(text)。它会去除空的文本节点,并且将毗邻的文本节点合并成一个,也就是说不存在空的文本节点,以及毗邻的文本节点。

3.11 其他接口的属性与方法

更多详细属性与方法请移步至MDN文档:Node 接口

4、Document接口的属性

4.1 document.body

该属性返回当前文档中的<body>元素。

1
2
3
4
5
6
7
8
// 如果HTML结构为<body id="oldBodyElement"></body>,则:
alert(document.body.id); // "oldBodyElement"

var aNewBodyElement = document.createElement("body");

aNewBodyElement.id = "newBodyElement";
document.body = aNewBodyElement;
alert(document.body.id); // "newBodyElement"

4.2 document.characterSet

该属性返回当前文档的字符编码。

1
document.characterSet   //"UTF-8"

4.3 document.children

该属性返回一个Node的子elements,是一个动态更新的HTMLCollection。

4.4 document.childElementCount

该属性返回一个无符号长整型数字,表示给定元素的子元素数。

4.5 document.documentElement

该属性是一个会返回文档对象的根元素。

对于任何非空HTML文档,调用document.documentElement总是会返回一个<html>元素,且它一定是该文档的根元素。

4.6 document.domain

该属性获取当前文档的域名。

1
document.domain //"zhouwanwen.com"

4.7 document.head

该属性返回当前文档中的<head>元素,如果有多个<head>元素,则返回第一个。

注意:document.head 是个只读属性,为该属性赋值只会静默失败,如果在严格模式中,则会抛出TypeError异常。

4.8 其他接口

更多详细属性请移步至MDN文档:Document 接口

5、Document接口的方法

5.1 document.close()

该方法用于结束对文档的 Document.write() 写入操作,这种写入操作一般由 Document.open() 打开。

1
2
3
4
5
6
7
8
// 打开一个文档,以便写入数据
document.open();

// 写入文档内容
document.write("<p>文档内容</p>");

// 关闭文档
document.close();

5.2 document.getElementById()

该方法返回一个匹配特定ID的元素。由于元素的 ID 在大部分情况下要求是独一无二的,这个方法自然而然地成为了一个高效查找特定元素的方法。

5.3 document.getElementsByClassName()

该方法返回一个包含了所有指定类名的子元素的类数组对象。当在document对象上调用时,会搜索整个DOM文档,包含根节点。你也可以在任意元素上调用getElementsByClassName() 方法,它将返回的是以当前元素为根节点,所有指定类名的子元素。

获取所有class为’demo’的元素:

1
document.getElementsByClassName('demo');

5.4 document.getElementsByName()

该方法根据给定的name返回一个在(X)HTML document的节点列表集合。

5.5 document.getElementsByTagName()

该方法返回一个包括所有给定标签名称的元素的HTML集合HTMLCollection。 整个文件结构都会被搜索,包括根节点。返回的 HTML集合是动态的, 意味着它可以自动更新自己来保持和 DOM 树的同步而不用再次调用 document.getElementsByTagName() 。

5.6 document.querySelector()

该方法返回文档中与指定选择器或选择器组匹配的第一个 html元素Element。 如果找不到匹配项,则返回null。

返回当前文档中第一个类名为”myclass”的元素:

1
2
var el = document.querySelector(".myclass")
console.log(el)

5.7 其他接口

更多详细方法请移步至MDN文档:Document 接口

6、Element接口的属性与方法

Element接口的属性与方法请移步至MDN文档:Element 接口

本文作者 : LqZww
原文链接 : http://yoursite.com/2019/11/11/js-li-de-dom/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
支付宝扫一扫, 向我赞赏

支付宝扫一扫, 向我赞赏

微信扫一扫, 向我赞赏

微信扫一扫, 向我赞赏

留下足迹