IE(<=8)中设置元素innerHTML值时,会忽略前面的无可显示内容的节点。

作者:  最后修改:2014年10月17日  浏览数:298

当需要大范围的修改页面元素的时候,往往使用innerHMTL属性批量处理。

但在IE8及之前的版本中,存在bug。

IE(<=8)中,使用innerHTML插入html元素时,会忽略第一个可显示字符的前面的无盒模型的元素(例如,link、script、style元素)。

注:可显示字符不是指实际将要显示的第一个字符,即使那个字符被样式隐藏了,只要可显示即视为可显示的字符。


这个bug常引起下面问题:

1.style中定义的样式在页面没起作用;

2.js插入的html代码中的script不存在。(如果你使用script作为html模板容器,会导致找不到这个script元素)。

bug修复方法:

  在要插入的html代码前添加类似于<div style=“display:none;”>hackIE</div>形式的内容,或使用jQuery的html方法处理。

 

概括的有点抽象。下面进行多个对比测试以彻底理解上面的结论。

 

下面是测试用页面代码:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="zh-CN" />
<title>set innerHTML in IE</title>
<script src="jquery-1.9.1.js"></script>

<!--下面是测试用的模板-->
<script type="text/template" id="template">
<div>
<span></span><i></i></div>
<p></p>
<div></div>
                

<link type="text/css" rel="stylesheet" href="1.css" />

<style>
body{background:#ff0;}
</style>
<p>通过innerHTML插入的html代码中的内容</p>
</script>
</head>
<body>
<div id="test">1111</div>
<div id="test2"></div>
</body>
</html>

在IE浏览器(浏览器模式调到IE8,标准)的控制台进行下面的测试。

实验一:
document.getElementById('test').innerHTML=document.getElementById('template').innerHTML;

执行后页面结构如下

   IE(<=8)

  标准浏览器效果(注意 link 和style元素也会包含进来)

 

实验二: 修改script中的模板,在无可显示内容的元素前面添加可显示的内容(此处为一个简单的字符q),模板修改为

<script type="text/template" id="template">
<div>
<span></span><i></i></div>
<p></p>
<div></div>

q

<link type="text/css" rel="stylesheet" href="1.css" />

<style>
body{background:#ff0;}
</style>
<p>通过innerHTML插入的html代码中的内容</p>
</script>

同样执行上面的设置innerHTML的语句

document.getElementById('test').innerHTML=document.getElementById('template').innerHTML;

测试结果如下:

  IE(<=8)

  这时的效果和预期一致。

类似的在处理script元素时也一样(script也是没有盒模型的元素)

测试如下:

控制台执行:

  document.getElementById('test2').innerHTML=document.getElementById('template').outerHTML+'SSS';

效果:

  IE(<=8)

 

  标准浏览器(结果包含script节点)

  

执行
document.getElementById('test2').innerHTML='q'+document.getElementById('template').outerHTML+'SSS';

(即使没盒模型的元素前有可显示的内容)

效果:

  IE(<=8)

  

(和标准浏览器一致,符合预期)

补充:Jquery中的相关方法 .html()

下面测试通过jQuery的html方法设置html效果:

执行

var html='<script>alert(1)</script><style>body{background:#ff0;}</style><script type="text/template">aaa<div>1111</div></script>';
$(body).html(html);

效果完全符合预期(script元素 的脚本会执行,而浏览器通过innerHTML设置时,不会解析script元素中的脚本)。

这是因为jQuery进行了兼容处理。

注:虽然jQuery中会解析插入的html代码中的js脚本,但当脚本中包含外部脚本时(script 通过src指定js文件),脚本的执行顺序是否能保持一致,还有待测试。(页面加载完后,在浏览器中通过 el.appendChild(scriptEl)形式先添加一个外部script脚本,然后立即再添加一个内部脚本script元素时,第二个脚本中往往不能访问第一个脚本文件中的定义的全局变量;如果想保存执行顺序,需通过回调处理)

综上:IE(<=8)中,使用innerHTML插入html元素时,会忽略第一个可显示字符的前面的无盒模型的元素(例如,link、script、style元素)。