由于需要写个函数,既可以加载css,又可以加载js,所以对各主流浏览器对加载js、css后是否触发onload事件做了个测试。当然,为了兼容,首先要考虑的是会用到onload和onreadystatechange,但他们并不是万能的。加载js文件onload触发callback不算大问题。css比较特殊,因为Webkeit/FF下加载css不会触发onload事件。所以研究了一晚上才找到个兼容的办法,分享如下:
首先测试元素直接写在页面
<link onload="alert('css onload')" rel="stylesheet" href="http://localhost/css/123.css"/> <script onload="alert('js onload')" src="http://localhost/123.js"></script> <link onreadystatechange="alert('css readystatechange')" rel="stylesheet" href="http://localhost/css/123.css"/> <script onreadystatechange="alert('js readystatechange')" src="http://localhost/123.js"></script>
CSS onload: 支持: IE6-9/OP, 不支持: FF/Webkit(SF/CM)
JS onload: 支持: IE9/OP/FF/Webkit, 不支持: IE6-8
CSS onreadystatechange: 支持: IE6-9, 不支持: OP/FF/Webkit
JS onreadystatechange: 支持: IE6-9, 不支持: OP/FF/Webkit
测试js创建元素
var doc = document, head = doc.getElementsByTagName("head")[0], css, js; css = doc.createElement('link'); css.href = 'http://localhost/123.css?2'; css.rel = 'stylesheet'; head.appendChild(css); js = doc.createElement('script'); js.src = 'http://localhost/123.js?2'; head.appendChild(js); css.onload = function(){ alert('css onload') } js.onload = function(){ alert('js onload') } css.onreadystatechange = function(){ alert('css readystatechange') //alert(this.readyState) //IE可以得到loading/complete, OP为undefined } js.onreadystatechange = function(){ alert('js readystatechange') //alert(this.readyState) //IE可以得到loading/loaded, OP为loaded }
CSS/JS onload:(同元素直接写在页面是一样的)
CSS onreadystatechange: 支持: IE6-9/OP, 不支持: FF/Webkit (这里有区别,OP支持js创建的css元素,但readyState为undefined)
JS onreadystatechange: 支持: IE6-9/OP, 不支持: FF/Webkit (这里有区别,OP支持js创建的js元素,readyState为loaded)
所以为了更大的兼容,onload、onreadystatechange都要写上,代码类似下面:
// 先把js或者css加到页面: head.appendChild(node); // onload为IE6-9/OP下创建CSS的时候,或IE9/OP/FF/Webkit下创建JS的时候 // onreadystatechange为IE6-9/OP下创建CSS或JS的时候 node.onload = node.onreadystatechange = function(){ // !this.readyState 为不支持onreadystatechange的情况,或者OP下创建CSS的情况 // this.readyState === "loaded" 为IE/OP下创建JS的时候 // this.readyState === "complete" 为IE下创建CSS的时候 if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") { node.onload = node.onreadystatechange = null; //防止IE内存泄漏 alert('loaded, run callback'); } }
jquery、kissy的源码,判断加载成功的核心部分差不多都这样实现的。
存在的问题:
1、当浏览器同时支持onload、onreadystatechange的情况会触发上面的函数两次,
比如:
IE9加载JS的时候,会alert两次,加载CSS的时候,alert一次,注释掉“onload、readystatechange=null”,alert两次。
OP加载JS/CSS,alert一次,把“onload、readystatechange=null”注释也会alert两次。
解决:
先在外部设定个变量isLoaded = false;
"if (!this.readyState..."上面加上个判断,如果已经加载成功就返回,比如:if (isLoaded) { return; }
"node.onload =..."上面加上 isLoaded = ture;
JQ有没有加这个我忘记了、KS应该是加了类似的判断了。
2、这个方法加载JS调用callback是兼容性没问题了,但是加载CSS再callback支持情况不同了:
IE6-9/OP可以成功alert,但是FF/Webkit不支持css的onload,解决办法: