表单元素虐你的地方

表单元素中的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.
</script>

   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))
posted @ 2016-10-28 15:50  Vins·lu  阅读(163)  评论(0编辑  收藏  举报