好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

简单的JS动态加载单体

简单的JS动态加载单体

原文来之: 博客园idche

前几天公司的项目需要这个功能,本来想找一个别人写的(别人的应该经过了许多测试,没啥问题)。

由于对这个功能的要求不高,只需要简单动态加在加载,不重复加载,简单的依赖就可以了。

最终还是自己花时间写了。

如果你熟悉YUI,

那么它跟YUI的工作方式很像

添加一个JS

WW.add( ' jQuery ' , ' http://code.jquery.com/jquery-1.6.1.min.js ' );

使用一个JS

 

WW.use( ' jQuery ' , function (){
document.getElementById( ' log ' ).innerHTML += ' <div>jQuery ok</div> ' ;
});


还有关于script标签的加载完成事件

/*
var script = document.createElement('script');
IE6 IE7 IE8 IE9 Chrome Firefox Opera
script.onreadystatechange null null -- null undefined undefined undefined
script.onload undefined undefined -- null null undefined null
*/

一般返回null 说明是当前浏览器支持的事件(firefox除外,firfox其实支持的是 onload)。

最重大的发现

当你直接在页面写SCRIPT标签,与动态创建的SCRIPT标签,Opera 浏览器的事件支持是不一样的。

直接创建:事件仅仅只有 onload

动态创建:加在完成事件有 onreadystatechange  onload

最终采用了 司徒正美 的方案(感谢,最后我觉得使用“document.dispatchEvent”还是有一定道理)。

support:document.dispatchEvent ? ' onload ' : ' onreadystatechange ' ,

源码(大约100行):

View Code

/* 动态JS加载 */
/*
var script = document.createElement('script');
IE6 IE7 IE8 IE9 Chrome Firefox Opera
script.onreadystatechange null null -- null undefined undefined undefined
script.onload undefined undefined -- null null undefined null
*/
/*
全局命名空间WW
主要方法
WW = {
add:fucntion(namespace, url){}
use:fucntion(namespaces, callback){}
}

方法 add(namespace, url, isOkay)
说明 注册一个JS模块
参数 namespace String
参数 url String
参数 isOkay Boolean 是否已经加载成功 可选 这个主要用于测试环境下很多文件,上线以合并成一个文件后注册空间不够

方法 use(namespaces, callback);
参数 namespaces String 可以是多个 namespace 使用逗号分割
参数 callback Function JS全部加载完成回调方法

*/
var WW = {
support:document.dispatchEvent ? ' onload ' : ' onreadystatechange ' ,
query:{ /* 队列 */ },
module:{ /* 成功注册的模块 */ },
add: function (namespace, url, isOkay){ // 注册一个命名空间
var module = this .module;

if (module[namespace]){
throw namespace + " is being " ;
}

module[namespace] = {};
module[namespace].url = url;
module[namespace].isOkay = isOkay || false ;
},
use: function (namespaces, callback){ // 使用一个命名空间

var task = {};
var key;

task.namespaces = namespaces.split( ' , ' );
task.callback = callback || function (){};
task.complet = 0 ; // 已完成
task.total = task.namespaces.length; // 总量
key = task.namespaces.join( '' ); // 任务的KAY;

this .query[ key ] = task;
this .start(task, key );

},
start: function (task, key){ // 内部 开始加载一个任务

var i = 0 ;
var len = task.namespaces.length;
var model;
var modelKey;

for (i; i < len; i ++ ){
modelKey = task.namespaces[i].replace( / ^\s+|\s+$ / g, '' );
model = this .module[ modelKey ];

if (model === undefined){
throw modelKey + ' is undefined ' ;
}

if (model.isOkay === false ){
model.isOkay = 1 ;
this .load(model.url, modelKey, key);
} else if (model.isOkay === true ){
this .checkBack(modelKey, key);
} else {
this .wait(model, modelKey, key);
}
}

},
wait: function (model, modelKey, key){ // 处理,后一个任务包含前一个正在进行中的任务,而导致的重复加载问题
var _this = this ;
var a = setInterval( function (){
if (model.isOkay === true ){
clearInterval(a);
_this.checkBack(modelKey, key);
}
}, 500 );
},
checkBack: function (modelKey, key){ // 内部
this .module[modelKey].isOkay = true ;
var query = this .query[key];
if ( ++ (query.complet) === query.total){
query.callback(); // 回调函数
delete this .query[key];
}
},
load: function (url, modelKey, key){ // 内部 加载一个JS
var _this = this ;
var script = document.createElement( ' script ' );

script[ this .support] = function (){
if ( / undefined|loaded|complete / .test(script.readyState) ){
_this.checkBack(modelKey, key);
}
};
script.setAttribute( ' type ' , ' text/javascript ' );
script.setAttribute( ' src ' , url);
document.getElementsByTagName( ' head ' )[ 0 ].appendChild(script);
}
};

测试例子

<!DOCTYPE html> <html> <head> <title>test</title> <mce:script type="text/javascript"><!-- /*动态JS加载*/ /* var script = document.createElement('script'); IE6 IE7 IE8 IE9 Chrome Firefox Opera script.onreadystatechange null null -- null undefined undefined undefined script.onload undefined undefined -- null null undefined null */ /* 全局命名空间WW 主要方法 WW = { add:fucntion(namespace, url){} use:fucntion(namespaces, callback){} } 方法 add(namespace, url, isOkay) 说明 注册一个JS模块 参数 namespace String 参数 url String 参数 isOkay Boolean 是否已经加载成功 可选 这个主要用于测试环境下很多文件,上线以合并成一个文件后注册空间不够 方法 use(namespaces, callback); 参数 namespaces String 可以是多个 namespace 使用逗号分割 参数 callback Function JS全部加载完成回调方法 */ var WW = { support:document.dispatchEvent ? 'onload' : 'onreadystatechange', query:{/*队列*/}, module:{/*成功注册的模块*/}, add:function(namespace, url, isOkay){//注册一个命名空间 var module = this.module; if(module[namespace]){ throw namespace+ " is being"; } module[namespace] = {}; module[namespace].url = url; module[namespace].isOkay = isOkay || false; }, use:function(namespaces, callback){//使用一个命名空间 var task = {}; var key; task.namespaces = namespaces.split(','); task.callback = callback || function(){}; task.complet = 0;//已完成 task.total = task.namespaces.length;//总量 key = task.namespaces.join('');// 任务的KAY; this.query[ key ] = task; this.start(task, key ); }, start:function(task, key){//内部 开始加载一个任务 var i = 0; var len = task.namespaces.length; var model; var modelKey; for(i; i<len; i++){ modelKey = task.namespaces[i].replace(/^\s+|\s+$/g,''); model = this.module[ modelKey ]; if(model === undefined){ throw modelKey+' is undefined'; } if(model.isOkay === false){ model.isOkay = 1; this.load(model.url, modelKey, key); }else if(model.isOkay === true){ this.checkBack(modelKey, key); }else{ this.wait(model, modelKey, key); } } }, wait:function(model, modelKey, key){// 处理,后一个任务包含前一个正在进行中的任务,而导致的重复加载问题 var _this = this; var a = setInterval(function(){ if(model.isOkay === true){ clearInterval(a); _this.checkBack(modelKey, key); } }, 500); }, checkBack:function(modelKey, key){//内部 this.module[modelKey].isOkay = true; var query = this.query[key]; if(++(query.complet) === query.total){ query.callback();//回调函数 delete this.query[key]; } }, load:function(url, modelKey, key){//内部 加载一个JS var _this = this; var script = document.createElement('script'); script[this.support] = function(){ if ( /undefined|loaded|complete/.test(script.readyState) ){ _this.checkBack(modelKey, key); } }; script.setAttribute('type', 'text/javascript'); script.setAttribute('src', url); document.getElementsByTagName('head')[0].appendChild(script); } }; // --></mce:script> </head> <body onload="load1();load2();load3();"> <div id="log"></div> <mce:script type="text/javascript"><!-- WW.add('jQuery', 'http://code.jquery.com/jquery-1.6.1.min.js'); WW.add('douban','http://img3.douban.com/js/packed_douban7312964743.js'); WW.add('ok','Jun.com.js', true); function load1(){ WW.use('jQuery', function(){ document.getElementById('log').innerHTML += '<div>jQuery ok</div>'; }); } function load2(){ WW.use('douban', function(){ document.getElementById('log').innerHTML += '<div>douban ok</div>'; }); } function load3(){ WW.use('douban,ok', function(){ document.getElementById('log').innerHTML += '<div>douban,ok ok</div>'; }); } // --></mce:script> <body> </html>

分类: JavaScript

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于简单的JS动态加载单体的详细内容...

  阅读:40次