這裏我們開始說一些有關於 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 的節點,有了一個大概的理解了。