一、前言
由于innerText并非W3C標準屬性,因此我們無法在FireFox中使用它(修正:FF45+已經支持innerText屬性),一般情況下我們可以使用textContent來代替,但它兩者是否就能完全等同呢?在坑爹的表單元素(如input、textarea等)中表現是否依舊詭異呢?文本將記錄一些實驗結果,避免日后被玩壞。
二、innerHTML
由于innerText和textContent均為對innerHTML內容作不同的處理而成,因此我們需要先明確innerHTML屬性的特點。
賦值操作:先對值內容進行模式匹配,然后把處理后的值賦予給innerHTML屬性。
模式匹配結果將導致 保留 和 將字符轉換為HTML實體 兩個操作。
a). 以下情況將被保留
1. HTML實體(ASCII實體、符號實體和字符實體)的實體名或實體編號;
2. 符號實體和字符實體對應的字符;
3. 沒有HTML實體與之對應的字符;
4. HTML標簽。(如<img>)
b). 以下情況將會執行字符轉換為HTML實體
1. ASCII實體對應的字符(<、>、&、'和")。
也就是說除了單獨的 <、>、&、'和" 會被轉換為實體名外,將原封不動地將值賦予給innerHTML屬性。
取值操作:直接獲取innerHTML屬性值。
后面的innerText和textContent內容將以下面的HTML Markup作為實驗原材料
<style type="text/css"> .line3, .line4{ float: left; } .line5::after{ content: "test" } </style> <div id="view"> <div>line1</div> <div>line2</div><br/> <div class="line3">line3</div> <div class="line4">line4</div> <div style="clear:both;"></div> <div class="line5">line5</div> </div> <script type="text/javascript"> var view = document.getElementById('view') </script>
二、innerText
瀏覽器支持:IE、Chrome
賦值操作:先將ASCII實體對應的字符(<、>、&、'和")轉換為實體名,然后把處理后的值賦予給innerHTML屬性。
取值操作:innerText的取值實際上就是對innerHTML的屬性值進行一系列處理,然后返回,具體步驟如下
1. 對HTML標簽進行解析;
2. 對CSS樣式進行帶限制的解析和渲染;
3. 將ASCII實體轉換為對應的字符;
4. 剔除格式信息(如\t、\r和\n等),將多個連續的空格合并為一個。
IE各版本和Chrome下對innerText進行取值均執行上述4步,但效果不盡相同。實驗結果如下:
IE5.5~8
頁面顯示效果:
line1
line2
line3line4
line5
innerText取值結果:
"line1
line2
line3line4line5"
不全面的小結:在進行CSS樣式渲染時,不支持偽元素和clear:both。
IE9~11
頁面顯示效果:
line1
line2
line3line4
line5test
innerText取值結果:
"line1
line2
line3
line4
line5"
不全面的小結:在進行CSS樣式渲染時,只會應用元素的默認樣式。
Chrome
頁面顯示效果:
line1
line2
line3line4
line5test
innerText取值結果:
"line1
line2
line3line4
line5"
不全面的小結:在進行CSS樣式渲染時,不支持偽元素。
三、textContent
瀏覽器支持:IE9~11、FireForx、Chrome
賦值操作:先將ASCII實體對應的字符(<、>、&、'和")轉換為實體名,然后把處理后的值賦予給innerHTML屬性。
取值操作:textContent的取值實際上就是對innerHTML的屬性值進行一系列處理,然后返回,具體步驟如下
1. 對HTML標簽進行剔除;
2. 將ASCII實體轉換為相應的字符。
注意:
a). 對HTML標簽是剔除不是解析,也不會出現CSS解析和渲染的處理,因此<br/>等元素是不生效的。
b). 不會剔除格式信息和合并連續的空格,因此\t、\r、\n和連續的空格將生效。
所有瀏覽器效果統一,界面效果:
line1
line2
line3line4
line5test
textContent取值結果:
" line1 line2 line3 line4 line5 "
四、表單元素中的innerHTML、innerText、textContent和value
到這里大家應該對innerHTML、innerText和textContent之間的關系和行為有一定了解了,但不幸的是表單元素一如既往地會推翻我們之前的理解。請注意的是上述的關系和行為僅限于非表單元素,而本節將介紹表單元素textarea和input[type="text"]相關的蛋疼……
前置信息: textarea和input[type="text"]的value屬性與界面輸入框是對應的,通過value屬性賦值與在界面輸入框輸入值屬于同一個操作。
textarea
FireFox
a). innerHTML可被設置并且生效,對其他屬性的影響:
1. 無條件影響textContent的取值;
2. 在通過value屬性賦值前,會影響value的取值;
3. 在通過value屬性賦值后,則value的取值與innerHTML無關。
b). textContent可被設置且生效,對其他屬性的影響:
1. 無條件影響innerHTML的取值;
2. 在通過value屬性賦值前,會影響value的取值;
3. 在通過value屬性賦值后,則value的取值與textContent無關。
c). value可被設置且生效。
Chrome
a). innerHTML可被設置并且生效,對其他屬性的影響:
1. 無條件影響innerText、textContent的取值;
2. 在通過value屬性賦值前,會影響value的取值;
3. 在通過value屬性賦值后,則value的取值與innerHTML無關。
b). innerText可被設置并且生效,對其他屬性的影響:
1. 無條件影響innerHTML、textContent的取值;
2. 在通過value屬性賦值前,會影響value的取值;
3. 在通過value屬性賦值后,則value的取值與innerText無關。
c). textContent可被設置且生效,對其他屬性的影響:
1. 無條件影響innerHTML、innerText的取值;
2. 在通過value屬性賦值前,會影響value的取值;
3. 在通過value屬性賦值后,則value的取值與textContent無關。
d). value可被設置且生效。
IE9~11
innerHTML、value、innerText和textContent均可設置且有效,無條件相互影響取值。
IE5.5~8
innerHTML、value、innerText和textContent均可設置且有效,無條件相互影響取值。
input[type="text"]
FireFox
a). innerHTML可被設置且生效,無條件影響innerText和textContent的取值,但不會影響value的取值。
b). textContent可被設置且生效,無條件影響innerHTML的取值,但不會影響value的取值。
c). value可被設置且生效,不會影響innerHTML和textContent的取值。
Chrome
a). innerHTML可被設置但無效,屬性值永遠保持空字符串。
b). textContent可被設置且生效,但不會影響value、innerHTML和innerText的取值。
c). innerText可被設置,但實際設置時會拋異常
<input type="text" id="target"> <script type="text/javascript"> var getDesc = function(){ return Object.getOwnPropertyDescriptor.apply(Object, arguments) } , get = function(){ return document.getElementById.apply(docuemnt, arguments) } var target = get('target'); console.log(getDesc(target, 'innerText')) // Object {value: "", writable: true, enumerable: true, configurable: true} target.innerText = "1" // NoModificationAllowedError: Failed to set the 'innerText' property on 'HTMLElement': The 'input' element does not support text insertion. </scr
d). value可被設置且生效,但不會影響textContent、innerHTML和innerText的取值。
IE5.5~8
a). innerHTML可被設置,但實際設置時會拋異常
<input type="text" id="target"> <script type="text/javascript"> var getDesc = function(){ return Object.getOwnPropertyDescriptor.apply(Object, arguments) } , get = function(){ return document.getElementById.apply(docuemnt, arguments) } var target = get('target'); console.log(getDesc(target, 'innerHTML')) // Object {value: "", writable: true, enumerable: true, configurable: true} target.innerText = "1" // 未知的運行時錯誤 </script>
b). innerText可被設置且有效,無條件影響value取值。但innerText的取值永遠是空字符串。
c). value可被設置且生效,但不會影響innerHTML和innerText的取值。
IE9~11
a). innerHTML可被設置且生效,無條件影響innerText和textContent的取值。但不影響value的取值。
b). innerText可被設置且生效,無條件影響value取值。但不影響innerHTML和textContent。innerText的取值由innerHTML的屬性值經過處理后返回。
// 假設a是input[type="text"] a.innerHTML = "<" a.innerText = "test" console.log(a.innerHTML) // < console.log(a.value) // test console.log(a.innerHTML) // <
c). textContent可被設置且生效,無條件影響innerHTML和innerText的取值,textContent的取值由innerHTML的屬性值經過處理后返回。
d). value可被設置且生效,但不會影響innerHTML、textContent和innerText的取值。
五、HTML編碼
所謂HTML編碼其實就是將字符轉換為HTML實體,這是防止腳本注入的重要手段之一。
由于表單元素的value與innerHTML關系在不同瀏覽器上表現各不相同,因此最保險的方式還是
;(function(exports, doc){ var dom = doc.createElement('textarea') exports.encode = function(raw){ dom.innerHTML = raw return dom.innerHTML } exports.decode = function(str){ dom.innerHTML = str return dom['innerText' in dom ? 'innerText' : 'textContent'] } }(window.htmlEncoder = {}, document))
六、總結
本文若有紕漏請大家指正補充,謝謝!
尊重原創,轉載請注明來自:http://www.cnblogs.com/fsjohnhuang/p/4319635.html ^_^肥仔John
文章列表