聊聊Node(節點)和Element(元素)有什麼區別?

2022-02-24 22:00:41
Node(節點)和Element(元素)有什麼區別?下面本篇文章給大家介紹一下Node 和 Element 的區別,希望對大家有所幫助!

相信我們很多同學都經常會使用到 Node(節點)和 Element(元素)的概念,那麼這兩者到底有何區別,不知道有多少人能夠答得上來這個問題?

今天,我在這裡嘗試著解釋一下 Node 和 Element 的區別。

【相關推薦:

準備工作

在正式開始介紹 Node 和 Element 區別之前,我們先準備以下程式碼:

<div id="parent">
    This is parent content.
    <div id="child1">This is child1.</div>
    <div id="child2">This is child2.</div>
</div>

下面的絕大多數現象和結論都將藉助這段程式碼的結構來進行展示說明。

getElementById 獲取到的到底是什麼?

document.getElementById() 方法應該是我們最常使用的介面之一,那麼它的返回值到底是 Node 還是 Element?

我們使用以下程式碼驗證一下:

let parentEle = document.getElementById('parent');
parentEle instanceof Node
// true
parentEle instanceof Element
// true
parentEle instanceof HTMLElement
// true

可以看到,document.getElementById() 獲取到的結果既是 Node 也是 Element。

Node、ELement 和 HTMLElement 有什麼關係?

上面的程式碼中為什麼要用 Node、Element 和 HTMLElement 來做型別判斷?它們之間到底有何關係?

看程式碼:

let parentEle = document.getElementById('parent');

parentEle.__proto__
// HTMLDivElement {…}

parentEle.__proto__.__proto__
// HTMLElement {…}

parentEle.__proto__.__proto__.__proto__
// Element {…}

parentEle.__proto__.__proto__.__proto__.__proto__
// Node {…}

parentEle.__proto__.__proto__.__proto__.__proto__.__proto__
// EventTarget {…}

parentEle.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__
// {constructor: ƒ, …}

parentEle.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__
// null

對於以上輸出結果,我們可以用一張圖更直觀地表示它們之間的關係:

1.png

這也就解釋了為什麼 getElementById 獲取到的既是 Node 也是 Element,因為 Element 繼承於 Node

從而也可以得出一個結論:Element 一定是 Node,但 Node 不一定是 Element

所以:Element 可以使用 Node 的所有方法

更直白地觀察 Node 和 Element

雖然得出了上面的結論,也清楚了 Node 和 Element 的關係,但是那只是理論,我們還需要更直白的結果來強化對理論的認知。

2.png

NodeList 內容:

  • [0] "\n This is parent content."
  • [2] "\n "
  • [4] "\n "

Element.children 獲取到的只是父元素點下的所有 div,而 Element.childNodes 獲取到的卻是父節點下的所有節點(包含文字內容、元素)。

單個 Node 的界限在哪裡?

從上面例子的 NodeList 內容中,換行符 \n 被當成一個單獨的 Node,由此產生了一個新的疑惑:單個 Node 產生的界限在哪裡?

我們將用到的 HTML 程式碼去掉格式化、合併為一行,修改如下:

<div id="parent">This is parent content.<div id="child1">This is child1.</div><div id="child2">This is child2.</div></div>

輸出結果:

3.png

NodeList 中的沒有換行符了,原來之前例子中 NodeList 裡的換行符是因為原始程式碼中, HTML 標籤與標籤、內容與標籤之間換行而產生的

現在就可以回答單個 Node 的界限在哪裡了,兩個方面:

  • 單個的 HTML 標籤算是一個單獨的 Node;
  • 針對非 HTML標籤(比如文字、空格等),從一個 HTML 標籤開始,到碰到的第一個 HTML 標籤為止,如果中間有內容(文字、空格等),那這部分內容算是一個 Node。注意:這裡的 HTML 標籤不分起始和結束。

比如,<div> 1 2 3 <span> 4 5 6 </span> 7 8 9 </div>,針對這段程式碼來說:

  • div 是一個 Node;
  • span 是一個 Node;
  • 「 1 2 3 」、「 4 5 6 」和 「 7 8 9 」全都是單獨的 Node

再進一步

因為上面的例子中使用的都是塊級元素,那如果使用行內元素會怎樣?

試驗一:

<div id="parent">This is parent content.<span>This is a span.</span><div id="child1">This is child1.</div><div id="child2">This is child2.</div></div>

4.png

試驗二:

<body>
    <div id="parent">This is parent content\n.
        <span>This is a span.</span>
        <div id="child1">This is child1.</div><div id="child2">This is child2.</div>
    </div>
</body>

5.png

可以看到,即使使用了 span 元素,最後的結果也是符合上面得出的單個 Node 界限結論的。

擴充套件

從以上這麼多例子中,我們可以再擴充套件總結一下:

  • HTML 中的換行只能使用 </br> 標籤,\n 會被直接解析成字串;
  • HTML 程式碼中,標籤與文字之間、標籤和標籤之間的換行都會被如實記錄,反映到獲取結果上就是 \n
  • HTML 程式碼中,標籤與標籤、文字與文字、文字與標籤之間的空格會被如實記錄;
  • node.data 內容中 \n 後面的空格字元數和實際程式碼中格式化空格設定數有關,其實也就是「空格會被如實記錄」。

總結

以上通過幾個例子說明了一下 Node 和 Element 之間的區別,主要結論總結起來就是:

  • document.getElementById() 獲取到的結果既是 Node 也是 Element。
  • Element 一定是 Node,但 Node 不一定是 Element,也可能是文字、空格和換行符。
  • NodeList 裡的換行符是因為原始程式碼中, HTML 標籤與標籤、內容與標籤之間換行而產生的。
  • 單個的 HTML 標籤算是一個單獨的 Node。
  • 針對非 HTML標籤(比如文字、空格等),從一個 HTML 標籤開始,到碰到的第一個 HTML 標籤為止,如果中間由內容(文字、空格等),那這部分內容算是一個 Node。

~ 本文完,感謝閱讀!

(學習視訊分享:)

以上就是聊聊Node(節點)和Element(元素)有什麼區別?的詳細內容,更多請關注TW511.COM其它相關文章!