Web前端之路饥人谷技术博客我爱编程

Javascript中DOM常见API

2018-11-25  本文已影响12人  长鲸向南

前言:尽管现在有很多优秀的框架,大大简化了我们的DOM操作,但是我们仍然要学好DOM知识来写原生JS,从根本上去理解,才更能在解决问题时举重若轻。

一、什么是DOM

D(document)O(object)M(model) 文档对象模型。

DOM(文档对象模型)是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义一种方式可以使从程序中对该结构进行访问,从而改变文档的结构、样式和内容。DOM将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。

上述说法是MDN的解释,太官方,我们来换种说法来解释。

DOM就是一种想象的树形结构,它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。

image

如上图,是我们文档的树形结构,我们通过DOM模型将上述结构一一映射成节点(通过构造函数把页面中的节点变成实例对象,dom就是这样把文档变成对象的),这些节点就又构成了节点树,也就是我们说的想象中的那棵DOM Tree。

二、Node

DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。

节点主要有7种类型:

所以文档树对应的节点树如同下图:

image

注:DOM树有3种层级结构:

值得注意的是,在上图中只有根节点也就是<html>对应的节点没有父节点。

三、Node接口

浏览器提供一个原生的节点对象Node,上面的7种节点均继承了Node,因此具有一些共同的属性和方法。这是DOM操作的基础。

image

1、属性

1.1 Node.prototype.nodeType

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

image

如上图,我们获取当前页面的body标签下的第一个孩子,是一个div标签,然后我们通过nodeType来看一下它的节点类型,结果返回了一个数字1,这代表着是一个Element节点。

【至于为什么会是返回一个数字而不是简单明了的返回Element,这也是由于历史原因,早期计算机内存紧张,为了节省内存使用了并无规律的数字】

常见的有以下:

Node.ELEMENT_NODE:1

Node.ATTRIBUTE_NODE:2

Node.TEXT_NODE:3

Node.COMMENT_NODE:8

Node.DOCUMENT_NODE:9

Node.DOCUMENT_TYPE_NODE:10

Node.DOCUMENT_FRAGMENT_NODE:11

1.2 Node.prototype.nodeName

nodeName属性返回节点名称

image

注:在元素节点中,返回名称基本都是大写,只有<svg>标签返回的是小写。

1.3 Node.prototype.nodeValue

nodeValue属性返回一个字符串,表示当前节点本身的文本值,该属性可读写。

只有文本节点(text)、注释节点(comment)和属性节点(attr)有文本值,因此这三类节点的nodeValue可以返回结果,其他类型的节点一律返回null

// html 代码如下
// <div id="d1">hello world</div>
var div = document.getElementById('d1');
div.nodeValue // null
div.firstChild.nodeValue //"hello world"

1.4 Node.prototype.textContent

textContent返回节点及后代节点的文本 ,即获取文本

这里和innerText一起讲:

早期并没有获取文本的API ,导致编码很繁琐,所以后来IE自己添加了一个API就是innerText,然后火狐和opera也推出了textContent

两者的区别:

1.5 Node.prototype.nextSibling

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

image

值得注意的是,该属性还包括文本节点和注释节点(``)。因此如果当前节点后面有空格或者回车,该属性会返回一个文本节点,内容为空格或回车。

document.body.nextSibling返回了文本节点或者注释节点,而我们需要获得是元素节点, 也可以用document.prototype.nextElementSibling直接获取该节点后面最接近的同级元素节点。

1.6 Node.prototype.previousSibling

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

Node.prototype.previousElementSibling 前一个同级元素节点

其他同1.5 一致

1.7 Node.prototype.firstChild,Node.prototype.firstElementChild

firstChild属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null
firstElementChild属性返回当前节点的第一个元素节点。

1.8 Node.prototype.lastChild,Node.prototype.lastElementChild

lastChild属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回null
lastElementChild属性返回当前节点的最后一个元素节点。

1.9 Node.prototype.childNodes

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

image

值得注意的是,除了元素节点,childNodes属性的返回值还包括文本节点和注释节点。如果当前节点不包括任何子节点,则返回一个空的NodeList集合。由于NodeList对象是一个动态集合,一旦子节点发生变化,立刻会反映在返回结果之中。

1.10 Node.prototype.children

children属性返回一个类似数组的对象(HTMLCollection),成员包括当前节点的所有子元素节点。

image

值得注意的是,这里就不会返回文本节点和注释节点了,它只会返回元素节点。由于HTMLCollection集合是动态集合,一旦子节点发生变化,立刻会反映在返回结果之中。

小tips : NodelistHTMLCollection 集合的区别

  1. NodeList可以包含各种类型的节点,HTMLCollection只能包含 HTML 元素节点.
  2. NodeList 实例可能是动态集合,也可能是静态集合。目前,只有Node.childNodes返回的是一个动态集合,其他的NodeList 都是静态集合。而HTMLCollection实例都是动态集合,节点的变化会实时反映在集合中.
  3. NodeList接口不同,HTMLCollection没有forEach方法,只能使用for循环遍历。

2、方法

2.1 Node.prototype.appendChild()

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

注意:

1、如果参数节点是 DOM 已经存在的节点,appendChild方法会将其从原来的位置移动到新位置。

2、如果appendChild方法的参数是DocumentFragment节点,那么插入的是DocumentFragment的所有子节点,而不是DocumentFragment节点本身。返回值是一个空的DocumentFragment .

2.2 Node.prototype.hasChildNodes()

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

注意:子节点包括所有类型的节点,并不仅仅是元素节点。哪怕节点只包含一个空格,hasChildNodes方法也会返回true

判断一个节点是否有子节点,有以下3种方法:

1、node.hasChildNodes()

2、node.firstChild ! == null

3、node.childNodes && node.childNodes.length > 0

2.3 Node.prototype.cloneNode()

cloneNode方法拷贝一个节点,并且可以接受一个布尔值,来表示是否同时拷贝子节点。它的返回值是一个克隆出来的新节点。

image image

深拷贝:深入进去全部拷贝,包括子节点。

浅拷贝:只拷贝节点本身。

值得注意的是,该方法返回的节点不在文档中,无任何父节点,必须用如appendChild()等方法添加。

2.4 Node.prototype.insertBefore()

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

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

2.5 Node.prototype.removeChild()

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

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

如果参数节点不是当前节点的子节点,removeChild方法将报错。

2.6 Node.prototype.replaceChild()

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

创造一个新儿子取代掉旧儿子,旧儿子去哪儿了?旧儿子去内存了。

2.7 Node.prototype.contains()

contains方法返回一个布尔值,表示参数节点是否为该节点的后代节点。

2.8 Node.prototype.isEqualNode(),Node.prototype.isSameNode()

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

image

所以说,isSameNode就等同于 ===严格相等运算符。

2.9 Node.prototype.normalize()

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

四、Document接口

document节点对象代表整个文档,每张网页都有自己的document对象。window.document属性就指向这个对象。只要浏览器开始载入 HTML 文档,该对象就存在了,可以直接使用。

document对象有不同的办法可以获取。

1、属性

1.1 用于指向其他节点(快捷获取某些特殊节点)的属性

1.2 返回文档特定元素的伪数组集合的属性

以上均为动态集合,而且除了document.styleSheets,以上的集合属性返回的都是HTMLCollection实例。

1.3 返回文档信息的属性

1.4 返回文档状态的属性

2、方法

五、Element接口

1、属性

2、方法

上一篇 下一篇

猜你喜欢

热点阅读