javascript库的延迟加载
如何控制js的加载顺序
如果只是简单的让js延迟加载,那只需要在页面尾部加上这样的代码:
var oHead = document.getElementsByTagName('HEAD').item(0);
var oScript= document.createElement("script");
oScript.id = id;
oScript.type = "text/javascript";
oScript.src=src;
oHead.appendChild(oScript);
但这样加载有个问题,如果我立刻在后面调用这个延迟加载的js里面的方法或者变量就会报错,因为新加载的js还没执行完呢。并且document的onload方法不会等待这样的延迟js加载成功。
还有就是这样加载的js不能保证顺序。也就是不能保证先append的js先执行。如果后面的js依赖于前面的js,而前面的js比较大,加载延迟,则后面的js执行的时候就可能报错。
我在修改这个高亮代码的脚本的时候就遇到了这样的问题。
并不是所有的文章都有代码,并且每篇文章可能出现的代码语言不一样,需要根据内容加载不同的库。
shCore.js是核心js,需要先加载。然后是各个语言的js,具体取决于文章内容中出现的代码语言。如 shBrushJava.js,shBrushBash.js等。
后面这些js都依赖于shCore.js。当所有的js都加载完的时候,才能调用:
SyntaxHighlighter.highlight();
高亮代码。
参考了一些文章,终于弄出一个解决方案:
if(!window.BrushUtils) var BrushUtils = (function(){
var ut = {
baseurl:"",
resources:[],
brushMap : {js:"JScript",jscript:"JScript",javascript:"JScript",
bash:"Bash",shell:"Bash",css:"Css",actionscript3:"AS3",as3:"AS3",cpp:"Cpp",c:"Cpp",
csharp:"CSharp",groovy:"Groovy",java:"Java",javafx:"JavaFX",jfx:"JavaFX",
perl:"Perl",pl:"Perl",php:"Php",text:"Plain",plain:"Plain",py:"Python",python:"Python",
ruby:"Ruby",ror:"Ruby",rails:"Ruby",scala:"Scala",sql:"Sql",xml:"Xml",html:"Xml",xhtml:"Xml",xslt:"Xml"
},
parseBrush :function(){
var pres = document.getElementsByTagName("pre");
var brushs = new Array();
for(var i=0;i<pres.length;i++){
var pre = pres[i];
var className = pre.className;
className = className.toLowerCase();
var bush = null;
if(className.indexOf('brush:')==0){
brush = className.substr(className.indexOf(':')+1);
}else if(pre.getAttribute('name')=='code'){
brush = className;
pre.className='brush:'+className;
}
if(brush==null)
continue;
if(!eval("ut.brushMap."+brush)){
pre.className='brush:text';
brush = "text";
}
if(!brushs.contains(brush)){
brushs.push(brush);
}
}
return brushs;
},
loadLibs : function(_baseurl,_theme){
var theme =_theme||"Default";
var baseurl = _baseurl;
ut.baseurl = baseurl;
var brushs = ut.parseBrush();
if(brushs.length==0)
return;
ut.loadStyle(baseurl+"styles/shCore.css");
ut.loadStyle(baseurl+"styles/shTheme"+theme+".css");
ut.resources.push({url:baseurl+'scripts/shCore.js',type:'js'});
for(var i=0;i<brushs.length;i++){
var lib = brushs[i];
lib = eval("ut.brushMap."+lib);
ut.resources.push({url:baseurl+"scripts/shBrush"+lib+".js",type:'js'});
}
ut.loadNext();
},
loadNext : function(){
if(ut.resources.length>0){
var resource = ut.resources.shift();
//var tempUt = ut;
var callback = ut.resources.length>0?function(){ut.loadNext();}:function(){SyntaxHighlighter.config.clipboardSwf = ut.baseurl+'scripts/clipboard.swf';SyntaxHighlighter.highlight();};
if(resource.type=='js'){
ut.loadJs(resource.url,callback);
}else if(resource.type='css'){
ut.loadStyle(resource.url,callback);
}
}
},
loadJs : function(src,callback){
var scriptTags = document.getElementsByTagName('script');
var oHead = document.getElementsByTagName('HEAD').item(0);
var script= document.createElement("script");
script.type = "text/javascript";
script.src=src;
script.onreadystatechange= function () {
if (this.readyState == 'loaded' || this.readyState == 'complete') {
callback();
}
}
script.onload= callback;
oHead.appendChild(script);
},
loadStyle : function(url){
var oHead = document.getElementsByTagName('HEAD').item(0);
var style= document.createElement("link");
style.type = "text/css";
style.rel="stylesheet";
style.href=url;
oHead.appendChild(style);
}
};
return ut;
})();
调用:
var syntaxhighlighter_url = "/scripts/syntaxhighlighter/"; BrushUtils.loadLibs(syntaxhighlighter_url);
主要在于对script的加载成功事件的监听。ie的事件是onreadystatechange,firefox的是onload.把需要加载的js放在一个队列里,当前一个加载完成时候,从队列里取出下一个js,继续加载。
经过测试,这个方法在ie,firefox,opera上都可以使用。但据说Safari上是没这个事件的(未测试)。
本来想给样式表也加上事件监听,结果发现样式表加载成功在firefox下是不触发事件的,ie下可以。
参考网址:
http://unixpapa.com/js/dyna.html
Related Posts
微软对google说:不要把手伸到我媳妇怀里
终于在网上建了个家
Javascript(Ajax)开发测试工具
Javascript对象中使用setTimeout和setInterval的问题
css强制换行问题
javascript获取网页元素的最终样式