打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
DOM系列:DOM節點屬性

經過前幾篇文章的學習,對DOM有一定的瞭解。但這僅僅是DOM一些基礎性的知識,如果要對DOM更瞭解,需要更深入地瞭解DOM節點。在這一節中,咱們將圍繞DOM的節點屬性、標籤和內容來展開。這樣我們就可以更進一步的瞭解它們是什麼?以及它們最常的屬性。

DOM節點類

DOM節點的屬性取決於它們的類(class)。例如,<a>標籤對應的是一個元素節點和鏈接a相關的屬性。文本節點與元素節點不一樣,但是它們之間也有相同的屬性和方法,因為所有的DOM節點會形成一個DOM樹。

每個DOM節點屬於相應的內置類。

root是DOM樹的EventTarget,它是由Node繼承的,而其他DOM節點繼承它。

下圖可以幫助我們更易於理解:

DOM節點的類主要有:

  • EventTarget:是root抽象類(Abstract Class)。該類的對象永遠不會創建。它作為一個基礎,因此所有的DOM節點都支持所謂的事件(Events),稍後會涉及這個
  • Node:也是一個抽象類,作為DOM節點的基礎。它提供了核心功能:parentNodenextSiblingchildNodes等(它們是getter)。節點類的對象沒有被創建。但是,有一些具體的節點類繼承了它,比如:文本節點的Text,元素節點的Element以及註釋節點的Comment
  • Element:是DOM元素的基本類。它提供了元素級的搜索,比如nextElementSiblingchilderngetElementsByTagNamequerySelector等。在瀏覽器中,不僅有HTML,還有XML和SVG文檔。元素類是更具體類的一些基礎,比如SVGElementXMLElementHTMLElement
  • HTMLElement:是HTML元素的基本類,它由各種HTML元素繼承。比如HTMLInputElemnt(對應input元素的類)、HTMLBodyElement(對應body元素的類)和HTMLAnchorElement(對應a元素的類)等

對於HTMLElement類,還有很多其它種,比如下圖所示的這些。

因此,節點的全部屬性和方法都是繼承的結果!

例如,DOM對象中的<input>元素。它屬於HTMLElement類中的HTMLInputElement類。它將屬性和方法疊加在一起:

  • HTMLInputElement:提供了input指定的屬性
  • HTMLElement:它提供常用的HTML元素方法(gettersetter
  • Element:提供元素通用方法
  • Node:提供公共的DOM節點屬性
  • EventTarget:提供對事件的支持(覆蓋)
  • 最後它繼承了Object的方法(純對象),比如hasOwnProperty

如果我們想查DOM節點類名,可以使用對象常用的constructor屬性。它引用類構造函數,可以使用constructor.name來獲取它的name。比如:

document.doctype.constructor.name                           // => DocumentTypedocument.documentElement.constructor.name                   // => HTMLHtmlElementdocument.head.constructor.name                              // => HTMLHeadElementdocument.body.constructor.name                              // => HTMLBodyElementdocument.getElementsByTagName('div')[0].constructor.name    // => HTMLDivElementdocument.getElementsByTagName('a')[0].constructor.name      // => HTMLAnchorElement

或者使用toString把它串起來,比如:

我們還可以使用instanceof來檢查繼承關係:

document.body instanceof HTMLBodyElement    // => truedocument.body instanceof HTMLElement        // => truedocument.body instanceof Element            // => truedocument.body instanceof Node               // => truedocument.body instanceof EventTarget        // => true

正如我們所看到的,DOM節點是常規的JavaScript對象。他們使用基於原型的類來繼承。

在瀏覽器中使用console.dir(elem)輸出元素也很容易。在控制台可以看到HTMLElement.prototypeElement.prototype等等。

DOM節點類型

瀏覽器和DOM一節中,我們知道瀏覽器會根據DOM模型,將HTML文檔解析成一系列的節點,再由這些節點組成一個DOM樹。在DOM中的最小組成單位叫做節點(Node),DOM樹由12種類型的節點組成。

DOM中的Node至少擁有nodeTypenodeNamenodeValue這三個基本屬性。節點類型不同,這三個屬性的值也會不相同。

  • nodeType:該屬性返回節點類型的常數值。不同的類型對應不同的常數值,12種類型分別對應112的常數值,如下面的表格所示
  • nodeName:該屬性返回節點的名稱
  • nodeValue:該屬性返回或設置當前節點的值,格式為字符串

nodeType節點類型:

節點類型 字符常量 數值常量
元素節點 Node.ELEMENT_NODE 1
屬性節點 Node.ATTRIBUTE_NODE 2
文本節點 Node.TEXT_NODE 3
CDATA節點 Node.CDATA_SECTION_NODE 4
實體引用名稱節點 Node.ENTRY_REFERENCE_NODE 5
實體名稱節點 Node.ENTITY_NODE 6
處理指令節點 Node.PROCESSING_INSTRUCTION_NODE 7
註釋節點 Node.COMMENT_NODE 8
文檔節點 Node.DOCUMENT_NODE 9
文檔類型節點 Node.DOCUMENT_TYPE_NODE 10
文檔片段節點 Node.DOCUMENT_FRAGMENT_NODE 11
DTD聲明節點 Node.NOTATION_NODE 12

而其中元素節點文本節點屬性節點是我們操作DOM最常見的幾種節點類型。

在JavaScript中,我們可以使用instanceof和其他基於類的測試來查看節點類型,但是有時候nodeType可能更簡單。

document.body.nodeType              // => 1document.doctype.nodeType           // => 10document.nodeType                   // => 9document.body.firstChild.nodeType   // => 1

nodeType是只能屬性,我們不能修改它。

DOM節點標籤

前面提到過nodeName將會返回節點名稱(返回的是HTML標籤,並且是大寫的)。也就是說,給定的DOM節點,可以通過nodeName屬性讀取它的標籤名稱,比如:

document.body.nodeName // => BODY

除了nodeName屬性之外,還可以通過tagName屬性來讀取:

document.body.tagName  // => BODY

雖然nodeNametagName都能讀取到元素標籤名,但兩者之間有區別嗎?當然,兩者之間有略微的差異:

  • tagName屬性只能用於元素節點(Element
  • nodeName屬性可以用於任意節點(Node)上,如果用於元素上,那麼和tagName相同,如果用於其他節點類型,比如文本、註釋節點等,它有一個帶有節點類型的字符串

也就是說,tagName只支持元素節點(因為它源於Element類),而nodeName可以用於所有節點類型。比如下面這個示例,來比較一下tagNamenodeName的結果:

<!DOCTYPE html><html lang="en">    <head>        <title>Learning the DOM</title>    </head>    <body>        <!-- 主內容 -->        <div id="main"></div>        <script>            console.log(document.body.firstChild.tagName)   // => undefined            console.log(document.body.firstChild.nodeName)  // => #text            console.log(document.tagName)                   // => undefined            console.log(document.nodeName)                  // => #document            console.log(document.body.tagName)              // => BODY            console.log(document.body.nodeName)             // => BODY        </script>    </body></html>

如果我們只處理DOM元素,那麼我們就可以選擇tagName屬性來做相應的處理。

除了XHTML,標籤名始終是大寫的。瀏覽器有兩種處理文檔的模式:HTML和XML。通常HTML模式用於Web頁面。當瀏覽器接收到一個帶有Content-Type:application/xml+xhtml的頭,就會啟用XML模式。在HTML模式中,tagName或者nodeName總是返回大寫標籤,比如<body><BoDy>返回的是BODY;對於XML模式,現在很少使用了。

DOM節點內容

對於DOM節點的內容,JavaScript中提供了幾個方法來對其進行操作,比如innerHTMLouterHTMLtextContentinnerTextouterTextnodeValue等。接下來,咱們看看他們的使用場景以及相應的差異性。

為了易於幫助大家理解和掌握這向方法的使用,接下來的示例都將圍繞著下面這個DOM結構來做處理:

<body>    <!-- 主內容 -->    <div id="main">        <p>The paragraph element</p>        <div>The div </div>        <input type="text" id="name" value="User name" />    </div></body>

innerHTML

innerHTML屬性允許我們獲取元素的HTML,而且其獲取的的值是一個String類型。比如:

let ele = document.getElementById('main')let eleContent = ele.innerHTML;console.log(typeof eleContent, eleContent)

輸出的結果如下:

上面看到的是innerHTML屬性獲取某個元素的內容,當然innerHTML也可以修改某個元素的內容。比如:

let eleP = document.querySelector('p')eleP.innerHTML = '我是一個段落,新修改的內容:<a href="#">我是一個鏈接</a>'

刷新頁面,段落p元素整個內容都將被修改了:

如果使用innerHTML<script>標籤插入到document,它不會被執行。

使用innerHTML可以使用ele.innerHTML += "something"來追回更多的HTML,比如下面這個示例:

let eleP = document.querySelector('p')eleP.innerHTML += '我是一個段落,新修改的內容:'eleP.innerHTML += '<a href="#">我是一個鏈接</a>'

結果如下:

使用innerHTML要非常小心,因為它做的不是加法,而是完整的覆蓋。還有:

當內容為“零輸出”(zeroed-out)和從頭重寫時,所有的圖像和其他資源將被重新加載。

outerHTML

outerHTML屬性包含元素的全部HTML。就像innerHTML的內容加上元素本身一樣。從文字難於理解或想像的話,咱們把上面的示例修改一下,通過innerHTMLouterHTML的結果來看其獲取的是什麼:

let eleP = document.querySelector('p')let eleInner = eleP.innerHTMLlet eleOuter = eleP.outerHTMLconsole.log('>>> innerHTML >>>', eleInner)console.log('>>> outerHTML >>>', eleOuter)

輸出的結果:

outerHTMLinnerHTML也可以寫入,但不同的是:

innerHTML可以寫入內容,改變元素,但outerHTML在外部環境中取代了整體!

比如下面這個示例:

let eleP = document.querySelector('p')eleP.outerHTML = '<div class="new">把整個p元素換成div元素</div>'

從效果和頁面源碼上截圖可以看出來,div替換了p

outerHTML賦值不修改DOM元素,而是從外部環境中提取它,並插入一個新的HTML片段,而不是它。新手時常在這裡會犯錯誤:修改eleP.outerHTML,然後繼續使用eleP,就好像它有新的內容一樣。

let eleP = document.querySelector('p')eleP.outerHTML = '<div class="new">把整個p元素換成div元素</div>'console.log(eleP.innerHTML)

我們可以寫入outerHTML,但是要記住,它不會改變我們寫入的元素。相反,它會在它的位置上創建新的內容。我們可以通過查詢DOM獲得對新元素的引用。比如:

let eleP = document.querySelector('p') eleP.outerHTML = '<div class="new">把整個p元素換成div元素</div>'console.log('>>>> ', eleP)let newEle = document.querySelector('.new')console.log('>>>> ', newEle)

結果如下:

textContent

textContent屬性和innerHTML以及outerHTML都不一樣。textContent只獲取元素的純文本內容,包括其後代元素的內容。比如:

let mainEle = document.querySelector('#main')console.log('>>>> innerHTML >>>>', mainEle.innerHTML)console.log('>>>> outerHTML >>>>', mainEle.outerHTML)console.log('>>>> textContent >>>>', mainEle.textContent)

結果如下:

正如我們所看到的,textContent返回的只有文本內容,就像是把所有HTML元素的標籤都刪除了,但是它們的文本仍然保留著。正如上面示例中的,innerHTMLouterHTMLtextContent輸出的結果,可以一目瞭然知道他們之間的差異性。

textContent和其他兩個屬性一樣,也可以寫入內容。但對於textContent的寫入更為有用,因為它寫入的內容是純內容,是一種安全方式。而innerHTMLouterHTML都會寫入HTML,而會寫入HTML標籤的方式是一種不安全的形式,容易引起Web的XSS攻擊。

XSS我們先忽略,來看看寫入的差異性:

let mainEle = document.querySelector('#main')let content = "我要新內容,並帶有一個標籤:<b>Boo,Waa!!!</b>"mainEle.textContent = contentmainEle.innerHTML = contentmainEle.outerHTML = content

效果如下:

如果你夠仔細的話,會發現,name中的<b>Boo,Waa!!!</b><body>標籤也被當做文本內容寫進去了。如下圖所示:

大多數情況之下,我們希望從用戶那裡得到文本,並希望將其視為文本。我們不希望在我們的網站上出現意想不到的HTML,那麼textContent就可以得到你想要的。

innerTextouterText

innerTextouterText是IE的私有屬性,獲取的也是元素的文本內容,有點類似於textContent。所以這裡只簡單的提一提,並不深入展開。如果這裡有誤,請大大們指正。

nodeValuedata

innerHTML屬性僅對元素節點有效。

其他節點類型有對應的節點:nodeValuedata屬性。這兩種方法在實際應用中幾乎是相同的,只有很小的差異。來看看示例。

<body>    Hello JavaScript!!!!    <!-- 主內容 -->    <div id="main">        <p>The paragraph element</p>        <div>The div </div>        <input type="text" id="name" value="User name" />    </div>    <script>        console.log('>>> nodeValue >>>', document.body.firstChild.nodeValue)        console.log('>>> data >>>', document.body.firstChild.data)    </script></body>

他們輸出的結果是相同的:

總結

每個DOM節點屬於某個類。這些類構成一個DOM樹。所有的屬性和方法都將被繼承。主要的DOM節點屬性有:

  • nodeType:我們可以從DOM對象類中獲取nodeType。我們通常需要查看它是否是文本或元素節點,使用nodeType屬性很好。它可以獲取對應的常數值,其中1表示元素節點,3表示文本節點。另外,該屬性是一個只讀屬性。
  • nodeName / tagNametagName只用於元素節點,對於非元素節點使用nodeName來描述。它們也是只讀屬性。
  • innerHTML:獲取HTML元素的內容(包括元素標籤自身)。其可以被修改。
  • outerHTML:獲取元素完整的HTML。outerHTML並沒有觸及元素自身。相反,它被外部環境中的新HTML所取代。
  • nodeValue / data:非元素節點的內容(文本、註釋)。這兩個幾乎是一樣的,不過我們通常使用data
  • textContent:獲取元素內容的文本,基本上是HTML減去所有的標籤。它也具有寫入特性,可以將文本放入元素中,所有特殊的字符和標記都被精確的處理為文本。

DOM節點也有其他屬性,這取決於它們的類。例如,<input>元素(HTMLElement)具有valuetype屬性,而<a>元素(HTMLAnchorElement)具有href屬性。大多數標準的HTML屬性都具有相應的DOM屬性。但HTML屬性和DOM屬性並不總是相同的,有關於這方面的介紹,我們在後面的文章中將會闡述。如果你感興趣,歡迎持續關注相關的更新。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
HtmlAgilityPack 之 HtmlNode类
详解JavaScript DOM中的Node节点
JavaScript之-文档对象模型(DOM)
JS中获取元素属性的方法
Html5 常见的新增API1. getElementsByClassName()方法
DOM节点信息、DOM属性、3大节点、替换节点、查找设置属性节点、创建删除插入节点、innerHTML属性、显示弹出窗口
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服