动态载入JavaScript
动态载入JavaScript非常简单,代码演示如下:
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'test.js';
head.appendChild(script);
侦测JavaScript是否载入
我们常常用JavaScript来给其它元素添加load事件,但如果给一个script自身添加load事件还真不是一件容易的事。对于非IE的高级浏览器来说和一般元素添加事件方法是一样的,代码演示如下:
script.onload=function(){
// do something
};
但对于IE来说则要复杂一点,不能直使用onload,而要使用onreadystatechange事件,通过onreadystatechange事件来判断script元素的readyState属性是否等于complete或者loaded,从而来确认script元素是否已经载入。代码演示如下:
script.onreadystatechange=function(){
if(this.readyState == 'loaded' || this.readyState == 'complete'){
// do something
}
};
readyState具有以下几个状态值:
- 0 : uninitialized
- 1 : loading
- 2 : loaded
- 3 : interactive
- 4 : complete
注意:在IE中complete或者loaded值是不会一起出现的,IE中会忽略一些状态,所以只需要判断它俩中的一个就可以了。
对于JavaScript不存在的处理
如果动态载入的JavaScript文件不存在的话,非IE浏览器会一直请求。在IE6、IE7中,script的属性值readyState会返回一个loading值,但有时候延迟久了会返回一个loaded值。而在IE8中,script的属性值readyState仍然会返回一个complete,这个很奇怪。
最终方案
这里根据jQuery里面的代码修改了下,增加了载入错误的回调功能。代码演示如下:
/**
* 动态载入 javascript 脚本
* @author <a href="mailto:jon.ju@msn.com">Jon</a>
* @param {Object} options 选项
* @param {String} options.url 脚本的 url 地址
* @param {Function} options.callback 脚本完成载入后回调的函数
* @param {Function} options.error 脚本没有按时载入时回调的函数
* @param {Number} options.time 请求超时时间,默认为 5 秒
* @param {String} options.charset 脚本的编码
*/
function insertScript(options){
var head = document.getElementsByTagName("head")[0] || document.documentElement,
script = document.createElement("script");
script.src = options.url;
var done=false, // 是否完成脚本载入的标识
timer; // 超时时间
if (options.charset) {
script.charset = options.charset;
}
script.onload = script.onreadystatechange = function() {
if ( !done && (!this.readyState ||
this.readyState === "loaded" || this.readyState === "complete") ) {
done = true;
// 如果有计时器,去除
if(timer)clearTimeout(timer);
if(options.callback)options.callback.call();
// 防止 IE 下的内存泄漏
script.onload = script.onreadystatechange = null;
if ( head && script.parentNode ) {
head.removeChild( script );
}
}
};
// 如果有错误回调函数,则超过一定时间就去除 script 的相关设置
if(options.error){
timer = setTimeout(function(){
// 如果还没有完成
if(!done){
script.onload = script.onreadystatechange = null;
if ( head && script.parentNode ) {
head.removeChild( script );
}
if(options.error){
options.error.call();
}
}
},options.time || 5000);
}
head.appendChild(script);
}
假设有个在动态载入的test.js文件,里面的代码是这样的:
var myVar = 'OK';
载入代码为:
insertScript({
'url':'test.js',
'callback':function(){
// IE 在文件不存在时也会触发 callback 函数,
// 所以在这里要加个判断
try{
alert(myVar);
}catch(e){
alert('error');
}
},
'error':function(){
alert('error');
},
'time':1000
});
如果test.js存在,则会alert出“OK”,如果文件不存在IE8会立即alert出“error”,而其它常用浏览器过1秒后会alert出“error”。