JavaScript进阶(二十一):父子节点,节点类型,document

这里我们开始说一些有关于 DOM 节点相关的一些事。

节点这个东西很简单,我们也叫它标签,平常我们用的 div,span 这些东西,都是节点。

当然,在这过程当中,节点它其实有很多很多的关系,远的我们不说,就说一近的。

比如,现在有一个 div,然后它里面还有一个 span:

那么这个 div,它就是 span 的父级。而 span,就是 div 的子级。

当然我们知道,一般情况下,父级只有一个,但是子级却可以有一堆,比如:

 

然后一般来讲,我们可以通过各种各样的一些东西,来获取它的父级或者子级。

其中,父节点是最容易用的,就直接叫做 parentNode

比如,现在来一个最简单的,我给一个 span 加上 id,然后我们来获取它,并且打印出它的 parentNode:

然后这个时候,你可以明确的看到,它的父级就是 div。

 

然后我们重点要说的其实是另外一个东西,就是除了父节点以外,我们还有子节点,而这个子节点,就稍微有一点麻烦了。

在我们的 js 里面,有两个方法来获取子节点:

一个叫做 children,相信这个东西大家很常用。

还有一个略微有点坑人,叫做 childNodes

从意思上来说,其实差不多:children 翻译过来就是孩子们,childNodes 翻译过来就是孩子节点们。

那有什么区别呢?我们来看看。

比方说,现在我把 div 它的 children 给拿出来:

你可以看到,它给我一个 HTMLCollection。

注意,所有通过这些获取元素的方式,出来的东西,它都不是真正的数组,它是一个类数组。

然后你可以看到它里面有 3 个 span。

 

然后接下来就是我们的 childNodes。

实际上来说,我们平常用 childNodes 用的少,但是有些情况下,你还就得用它,没它就不行,怎么回事呢?

我们先来看一下效果:

注意,实际上来说,你可以看到,它里面除了 3 个 span 以外,还有一堆的 text,这是什么意思?

所谓 text,其实是一种有点特殊的节点类型,叫做文本节点。

我们平常的这种 span,h1,div 这些东西,叫做 ElementNode 元素节点,而 textNode,它叫做文本节点。

那么这时候,比方说,我在上面弄一行字:

那这个文本节点,一目了然。

你可以看到,就是它:

那么反过来,我们可能会有点奇怪。

比如说,这 3 个 span 之间,它们怎么还有文本呢?

其实这些文本都是你加的。

简单来说,空格,对于我们人类来说,可能是个没意义的字符。

但对于计算机来说,它就是一个字,空格也是字。

所以说,在这种情况下,你这里的空格,它也会变成一个文本节点,叫做空文本节点。

 

当然,假设我把这几个 span 之间的空格,给它彻底删除。

那么这时候你可以看到:

就只剩下 5 个了。

3 个 span 之间是不是就空了?

就这么简单,就是那几个换行。

 

当然,这时候我们也就要说说了,为什么这个 childNodes 不太常用,其实原因就在这了。

因为这个 childNodes,它不光包括元素节点,比如那几个 span。

它也包括文本节点,就像上面,不管你是有字的,还是空的,它都包含。

 

但是,我们平常来讲,几乎不太会去直接操作文本节点,因为它只是我们的内容,我们不太会操作它。

比方说,我们加个样式,加个事件,都是对元素而言,文本节点你也加不上事件。

所以这就是为什么,平常它不太常用的原因。

 

所以,children 的特点,就是只有元素节点,别的一律没有。

childNodes,它是所有的节点,它都有。既包括元素节点,也包括文本节点,甚至于还包括注释节点和其他的一些东西。

比如:

那么这时候你可以看到,它里面除了 text 以外,还多了一个 comment,也就是注释节点。

这个注释节点,对我们平常而言,几乎是没有任何实际意义的。

当然,以后我们会用到它的,因为它的性能最高。

 

反正你就记住一件事,children 只有元素,而 childNodes 什么都有。

正因为 childNodes 什么都有,所以比较乱,这就是为什么我们平常用它比较少的原因。

那么现在,我们就了解了,子节点其实分成两种。

 

接下来,我们还要说一个事情,就是,节点其实是有类型的。

就比如说,刚才的 childNodes,因为某种原因,我现在就需要用它,那么这时候,我在循环的时候,是不是就得小心一点?我得看一看,到底是什么东西,给我的是个元素,还是个文本,或者是注释,还是个别的东西。

所以,每一个节点,只要是 HTML 里面的节点,它都有一个类型。

每个节点身上都有一个东西,叫做 nodeType。

那么我们来实验一下,比如 div 下面的第一项是什么?

可以看到,它就是一个文本,一些字。

然后,我们主要想看看它的类型是什么:

那么这个时候你可以看到,它给我们一个 3。

 

实际上来说,节点类型这个东西,是以数字的形式来存在的。

当然有人会说,记不住啊,这谁能记得住?

其实这个倒不用你去记,因为首先,常用的就 2、3 个。其次,我们的 document 上,其实有它原始类型的定义。

比方说:

注意,它是全大写的,因为它是一个常量。

那么这时候你可以看到,是一个 true,说明它是一个文本节点。

 

当然除了这些以外,还有很多别的一些节点。

比方说,现在我们要第一个 div.childNodes[1],也就是 span:

现在这时候你可以看到,它就是一个 span,并且是一个 1。

当然这个 1,它也有自己相应的一个类型定义,document 上有一个东西叫做 ELEMENT_NODE,元素节点。

你可以看到,是 true。

 

所以这时候,我们就看到了:

nodeType,首先它是一个数字。

其次,这个数字有一些比较常用的:

我们比较常用的 1,它对应的是 document.ELEMENT_NODE,元素节点。

然后还有一个 3,这个对应的是 document.TEXT_NODE,文本节点。

 

然后现在我们就来看看第五个节点,注释节点:

这时候,你可以看到,它是一个 8,它对应的就是 document.COMMENT_NODE,注释节点。

所以这时候,我们就又看到了一个东西。

 

当然,这个 nodeType 的类型其实是挺全的,它里面不光包括这种我们平常能够用的着的类型,甚至于还包括一些比较怪异的类型,或者说不太常用的一些类型。

比方说,在我们整个的 DOM 操作的过程当中,其实有一个节点是最特殊的,这个节点叫做 document。

document 它其实也是一个虚拟的 HTML 节点,我们先把它打印出来看看:

 

这个 document,我们需要稍微来认识它一下,我们老用到 document,那它到底是什么?到底什么叫 document?

首先是这样的,我们先来看一个特别有意思的现象。

document 上有一个很特殊的东西叫做:document.documentElement

当然,平常我们都是用的 document.body:

document.body 我们都用过,这就是 body,没啥可说的。

那么,这个 document.documentElement 它是什么呢?

其实它就是 html。

你可以看到,其实 document.documentElement,它就是 html 的简称。

当然,它是没有 document.html 的:

这个是空的,没有的。

 

那么现在,我就想看一个最简单的东西,document.documentElement.parentNode 是谁?

换句话说,我们平常从来没有探究过 html 的父级是谁。

我明确的告诉大家,html 的父级,你一天到晚都在用,就是 document

换句话说,其实你可以这么理解:

就是说,document,你可以认为是一个看不见的顶级元素,我们所有的这些 HTML 的东西,全都在 document 里面。

当然,这只是为了便于大家去理解,实际上来说,这个 document,你是不能写出来的,也没人这么写。

所以我们知道了:document 是 html 元素的父级。

 

然后这个 document,其实它是一个接口,它本身其实并不是一个真的节点,因为不用我们写。

然后它里面保存了各种各样的方法,可以帮助你来调用 HTML 里面的各种东西,比方说 getElementById,你没有这些方法,你根本就操作不了 DOM。

 

既然我们说 document 它也是一个特殊的节点,那么是节点,它就有 nodeType,那么这时候我们可以来看一下:

你可以看到,它也是给我们一个数字的值 9。

9 这个值,它对应的类型就是 document.DOCUMENT_NODE:

实际上来说,在我们整个 HTML 里面,就它一个人是 9 这个类型,没有第二个。

当然,这个我们了解一下就行,平常也用不到这个。

 

那么这时候,你可能会奇怪,你怎么 1,3,8,9 跳着来? 2,4,5,6 之类的去哪了?

实际上来说,像 2,4,5,6 之类的,它并不是那么常用的一些类型。

比如像 2,平常大家几乎碰不到,它是一种 ATTRIBUTE_NODE 类型,就是一个所谓的属性节点。

 

当然,这个东西在我们的 HTML 里面,几乎不太会用到。这时候大家可能会奇怪,不太用到,那为啥会有它?

没什么,因为 HTML 是 XML 的一个子级。

实际上来说,XML 里面是有 ATTRIBUTE_NODE 的,所以它就继承过来了。

所以除了 1,3,8,这三个以外,其他的类型,我们一般也用不着。

 

那么接下来有一个问题,document 有父级吗?

首先你得规定一下,怎么就叫父级。按照我们一般的约定,我们认为 parentNode 就是父级:

那么你可以明确的看到,就是 null。

不好意思,document 我就是头,我没有父级。

当然,从对象本身的所属关系上,它是属于 window 的:

因为,全局的东西,我们说都属于 window。

document 也是一个全局的东西,所以它当然属于 window。

所以我们就知道了,document 是没有节点上的父级。

 

那么到这为止,我们就已经大概的理解了这个东西,稍微的来总结一下:

首先,我们说了一个很重要的东西,就是说这个节点,它之间是有关联的,比如父节点,子节点。

父节点就一个,parentNode,没了。

而子节点有两个,children 和 childNodes:

children,它只有元素节点,我们平常一般都用它。

childNodes,它就是所有节点的一个大集合。

 

然后我们在处理节点的时候,往往需要知道这个节点到底是什么类型的,我好对症下药。

那么这时候你就需要用到 nodeType 这样的一个属性。

这个是所有节点都有的一个属性,并且它就是一个数字,当然也对应了一些值:

1  document.ELEMENT_NODE

3  document.TEXT_NODE

8  document.COMMENT_NODE

9  document.DOCUMENT_NODE

 

然后 document,它实际上来说,其实是一个虚拟的父级,整个 html 的顶点。

那么现在,我们就对这个 DOM 的节点,有了一个大概的理解了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章