问题描述
onreadystatechange 事件通常用在基于 XMLHttpRequest 对象的 AJAX 应用中,当的该对象的 load state 改变时,会触发此事件。
但在 IE 中 onreadystatechange 事件是其私有实现的,用于数据加载的 IMG、SCRIPT 和 LINK 标记,常常被误用 onreadystatechange 事件而导致在非 IE 浏览器中无法得到预期结果。
造成的影响
onreadystatechange 事件处理在各浏览器支持不一致,可能会导非预期结果。
受影响的浏览器
| IE6 IE7 IE8 |
|---|
问题分析
onreadystatechange 事件是微软对 IE 浏览器的私有事件扩充,所有元素都存在 onreadystatechange 事件。
下列元素对象总可以触发此事件,因为他们均会加载数据:APPLET,DOCUMENT,FRAME,FRAMESET,IFRAME,IMG,LINK,OBJECT,SCRIPT 和 XML 元素。
其他元素对象仅当 DHTML Behavior 被追加后会触发 onreadystatechange 事件。
其具体信息可以参照 MSDN 说明:http://msdn.microsoft.com/en-us/library/ms536957(VS.85).aspx。
本文中将主要以 IMG、SCRIPT、LINK 这三个元素对象为例来检测浏览器对他们的 onreadystatechange 事件支持程度。
首先,分析以下代码,将 onreadystatechange 事件作为内联事件分别写于 IMG、SCRIPT 和 LINK 标记中:
<script>
function OnStateChangeImage(image) {
document.getElementById ('img-info').innerHTML += '<br />readyState: ' + image.readyState;
}
function OnStateChangeScript(script) {
document.getElementById ('script-info').innerHTML += '<br />readyState: ' + script.readyState;
}
function OnStateChangeLink(link) {
document.getElementById ('link-info').innerHTML += '<br />readyState: ' + link.readyState;
}
</script>
<span id="link-info" >The link is loading.</span><br />
<span id="img-info" >The image is loading.</span><br />
<span id="script-info">The script is loading.</span><br />
<link rel="stylesheet" type="text/css" href="../../../../../css/article.css" onreadystatechange="OnStateChangeLink(this)" />
<img src="w3c.png" onreadystatechange="OnStateChangeImage (this)" />
<script src='http://code.jquery.com/jquery-1.4.js' onreadystatechange="OnStateChangeScript(this)"></script>
在各浏览器输出如下:
| IE6 IE7 IE8 | Firefox Safari Chrome Opera | |
|---|---|---|
| IMG | The image is loading. The image readyState: complete | The image is loading. |
| SCRIPT | The script is loading. The script readyState: loading The script readyState: loaded The script readyState: complete | The scirpt is loading |
| LINK | The link is loading. The link readyState: complete | The link is loading |
即:非 IE 浏览器均不支持触发 IMG、SCRIPT 和 LINK 标记的内联 onreadystatechange 事件。
让后,下面将分析动态创建的 IMG、SCRIPT 标记的在各浏览器中能否触发 onreadystatechange 事件:
function loadJS(url) {
var domScript = document.createElement('script');
domScript.onreadystatechange = function() {
var divElement = document.createElement('div');
divElement.appendChild(document.createTextNode('readyState:'+ domScript.readyState +' 动态创建的 SCRIPT 标记可以触发 onreadystatechange 事件'));
document.body.appendChild(divElement);
}
domScript.src = url;
document.getElementsByTagName('head')[0].appendChild(domScript);
}
function loadIMG(url) {
var domImage = document.createElement('img');
domImage.onreadystatechange = function() {
var divElement = document.createElement('div');
divElement.appendChild(document.createTextNode('readyState:'+ domImage.readyState +' 动态创建的 IMG 标记可以触发 onreadystatechange 事件'));
document.body.appendChild(divElement);
}
domImage.src = url;
document.getElementsByTagName('head')[0].appendChild(domImage);
}
function loadCSS(url) {
var domLink = document.createElement('link');
domLink.onreadystatechange = function() {
var divElement = document.createElement('div');
divElement.appendChild(document.createTextNode('readyState:'+ domLink.readyState +' 动态创建的 LINK 标记可以触发 onreadystatechange 事件'));
document.body.appendChild(divElement);
}
domLink.rel = 'stylesheet';
domLink.type = 'text/css';
domLink.href = url;
document.getElementsByTagName('head')[0].appendChild(domLink);
}
window.onload=function (){
//执行动态加载外部 JS 文件
loadJS('http://code.jquery.com/jquery-1.4.js');
//执行动态加载图片文件
loadIMG('w3c.png');
//执行动态加载css文件
loadCSS('../../../../../css/article.css');
}
各浏览器输出如下:
| IE6 IE7 IE8 | Opera | Firefox Safari Chrome | |
|---|---|---|---|
| IMG | readyState:complete 动态创建的 IMG 标记可以触发 onreadystatechange 事件 | readyState:undefined 动态创建的 IMG 标记可以触发 onreadystatechange 事件 | 无内容输出 |
| SCRIPT | readyState:loading 动态创建的 SCRIPT 标记可以触发 onreadystatechange 事件 readyState:loaded 动态创建的 SCRIPT 标记可以触发 onreadystatechange 事件 | readyState:loaded 动态创建的 Script 标记可以触发 onreadystatechange 事件 | 无内容输出 |
| LINK | readyState:complete 动态创建的 LINK 标记可以触发 onreadystatechange 事件 | readyState:undefined 动态创建的 LINK 标记可以触发 onreadystatechange 事件 | 无内容输出 |
可见,此次测试中,除 IE 浏览器外,Opera 对于动态创建的 IMG、SCRIPT 和 LINK 标记也可以触发 onreadystatechange 事件,但他对不同元素加载过程中触发该事件的频率以及 readyState 状态值的支持细节又不同于 IE。
【注】:对于 MSDN 中其他标记或对象在非 IE 浏览器中支持 onreadystatechange 事件的情况,本文将不再一一验证,读者如有兴趣可以自行测试。
解决方案
在现行 W3C 标准规范中仅有 XmlHttpRequest 对象中存在 onreadystatechange 事件 ( 请参考 XMLHttpRequest 规范 )。
对于其他元素或对象请慎用 onreadystatechange 事件,因为他只有 IE 浏览器支持,而 Opera 浏览器则只是部分支持。
如果使用 onreadystatechange 是为了处理脚本加载(回调)的问题,请参考 BX9013: 动态引入的外部 JS 文件在各浏览器中的加载顺序不一致 一文“解决方案”中的内容。
本文探讨了onreadystatechange事件在不同浏览器中的表现,特别是IE浏览器与其他浏览器之间的差异。文章通过实例展示了该事件在IMG、SCRIPT和LINK元素上的触发情况,并提供了使用建议。

314

被折叠的 条评论
为什么被折叠?



