表单元素虐你的地方
表单元素中的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) // <
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))