[1]innerHTML [2]outerHTML [3]innerText [4]outerText [5]textContent ...
×
目錄
[1]innerHTML [2]outerHTML [3]innerText[4]outerText[5]textContent前面的話
<p>This is a <i>simple</i> document</p>
上面這行代碼中,<p>元素的內容是什麼呢?答案一:內容是HTML字元串"This is a <i>simple</i> document";答案二:內容是純文本字元串"This is a simple document";答案三:內容是一個Text文本節點、一個包含了Text文本子節點的Element元素節點和另外一個Text文本節點
三個答案都正確,不同的答案從不同的角度描述了元素內容。本文將詳細介紹描述元素內容的5個屬性
innerHTML
innerHTML屬性可讀可寫。在讀模式下,返回與調用元素的所有子節點(包括元素、註釋和文本節點)對應的HTML標記;在寫模式下,innerHTML會根據指定的值創建新的DOM樹,然後用這個DOM樹完全替換調用元素原先的所有子節點
[註意]IE8-瀏覽器會將所有標簽轉換成大寫形式,且不包含空白文本節點;而其他瀏覽器則原樣返回
<p id="test">This is a <i>simple</i> document</p> <script> console.log(test.innerHTML);//'This is a <i>simple</i> document' test.innerHTML = 123; console.log(test.innerHTML);//'123' </script>
如果將innerHTML屬性設為空,等於刪除所有它包含的所有節點
<p id="test">This is a <i>simple</i> document</p> <script> test.innerHTML = ''; console.log(test.childNodes.length);//0 </script>
[註意]在IE9-瀏覽器中,不支持innerHTML的屬性有:<col>、<colgroup>、<frameset>、<head>、<html>、<style>、<table>、<tbody>、<thead>、<tfoot>、<tr>。在IE8-瀏覽器中<title>元素也沒有該屬性
<table id="test"></table> <script> test.innerHTML = '1' //在IE9-瀏覽器中報錯,其他瀏覽器返回1 console.log(test.innerHTML); </script>
無論什麼時候,只要使用innerHTML從外部插入HTML,都應該首先以可靠的方式處理HTML。IE瀏覽器提供了window.toStaticHTML()方法,這個方法接收一個參數,即一個HTML字元串;返回一個經過無害處理後的版本——從源HTML中刪除所有腳本節點和事件處理程式屬性
var text = "<a href='#' onclick = 'alert(\"hi\");'>Click Me</a>"; var sanitized = window.toStaticHTML(text); //只有IE支持 console.log(sanitized);//<a href="#">Click Me</a>
效率
在元素上設置innerHTML屬性調用了Web瀏覽器的解析器,通常設置innerHTML效率非常髙,甚至在指定的值需要解析時效率也是相當不錯
<ul id="test1"></ul> <ul id="test2"></ul> <script> console.time("time"); for(var i = 0; i < 10000;i++){ var oLi = document.createElement('li'); test1.appendChild(oLi); } //15.842ms console.timeEnd('time'); /****************************/ console.time("time"); var sHtml = ''; for(var i = 0; i < 10000; i++){ sHtml += '<li></li>'; } test2.innerHTML = sHtml; //5.373ms console.timeEnd('time'); </script>
從上面可以看出,使用innerHTML比appendChild()的性能高出不少
[註意]對innerHTML屬性用“+=”操作符重覆追加一小段文本通常效率低下,因為它既要序列化又要解析
<ul id="test"></ul> <script> console.time("time"); for(var i = 0; i < 10000; i++){ test.innerHTML += '<li></li>'; } //time: 50416.330ms console.timeEnd('time'); </script>
可以看出,對innerHTML屬性使用'+='操作符的性能嚴重低下,所以一定不要這麼使用
outerHTML
outerHTML同樣可讀可寫,與innerHTML相比,它包含被查詢元素的開始和結束標簽。在讀模式下outerHTML返回調用它的元素及所有子節點的HTML標簽;在寫模式下,outerHTML會根據指定的HTML字元串創建新的DOM子樹,然後用這個DOM子樹完全替換調用元素
[註意]IE8-瀏覽器會將所有標簽轉換成大寫形式,且不包含空白文本節點;而其他瀏覽器則原樣返回
<p id="test">This is a <i>simple</i> document</p> <script> console.log(test.outerHTML);//<p id="test">This is a <i>simple</i> document</p> test.outerHTML = '<div id="test"></div>'; console.log(test.outerHTML);//'<div id="test"></div>' </script>
innerText
innerText屬性可以操作元素中包含的所有文本內容,包括子文檔樹中的文本。在通過innerText讀取值時,它會按照由淺入深地順序,將子文檔樹中的所有文本拼接起來。在通過innerText寫入值時,結果會刪除元素的所有子節點,插入包含相應文本值的文本節點
<p id="test">This is a <i>simple</i> document</p> <script> console.log(test.innerText);//'This is a simple document' test.innerText = '<div id="test"></div>'; console.log(test.innerText);//'<div id="test"></div>' //即使在innerText中設置元素節點,最終也只是作為字元串內部的文本顯示 console.log(test.childNodes[0].nodeType);//3 </script>
因此,設置innerText屬性只會生成當前節點的一個子文本節點Text。因此,可以利用將innerText設置為等於innerText來去掉所有HTML標簽
<p id="test">This is a <i>simple</i> document</p> <script> console.log(test.innerHTML);//'This is a <i>simple</i> document' test.innerText = test.innerText; console.log(test.innerHTML);//'This is a simple document' </script>
outerText
在讀取文本值時,outerText與innerText的結果完全一樣,但在寫模式下,outerText不只是替換調用它的元素的子節點,而是會替換整個元素
<p id="test">This is a <i>simple</i> document</p> <script> console.log(test.outerText);//'This is a simple document' test.outerText = '123'; console.log(document.body.childNodes[0]);//' 123' //報錯,因為<p>元素已經被替換為'123',不再存在了 console.log(test.outerText); </script>
textContent
textContent屬性與innerText屬性類似,該屬性可讀寫。在讀模式下,返回當前節點和它的所有後代節點的文本內容;在寫模式下,結果會刪除元素的所有子節點,插入包含相應文本值的文本節點
[註意]IE8-瀏覽器不支持該屬性
<p id="test">This is a <i>simple</i> document</p> <script> console.log(test.textContent);//'This is a simple document' test.textContent = '<div id="test"></div>'; console.log(test.textContent);//'<div id="test"></div>' //即使在textContent中設置元素節點,最終也只是作為字元串內部的文本顯示 console.log(test.childNodes[0].nodeType);//3 </script>
與innerText不同的是,textContent屬性不僅屬於元素節點ElementNode,而是屬於所有節點Node
<p id="test">This is a <i>simple</i> document</p> <script> var oText = test.childNodes[0]; console.log(oText.textContent);//'This is a ' console.log(oText.innerText);//undefined </script>
最後
在firefox以前的版本中不支持innerText和outerText,但是隨著firefox的更新換代,這兩個屬性也開始支持。所以,上面的5個屬性的相容問題都來源於IE8-瀏覽器。IE8-瀏覽器不支持textContent屬性,IE8-瀏覽器在使用innerHTML和outerHTML屬性時,會將所有標簽轉換成大寫形式,且不包含空白文本節點
上面5個屬性中,常用的是innerHTML、outerHTML和innerText這3個