文章出處

一、前言                              

  由于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) // &lt;
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


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()