最近由於工做須要作了一個js自動導入的插件,一開始很天真的覺得動態建立個script添加到head中就ok了,試了以後才發現了問題,就是若是同時引入了多個js文件,並且後一個文件中用到了前一個文件中的變量,那就會報錯,靠~~悲催了,就是說js若是動態加載(非瀏覽器加載由於瀏覽器加載時同步加載的會等待前一個js加載完成後才進行下一個js加載,這樣就不會出現問題)那加載的文件是異步進行的,難怪啊!而後在網上找了些資料說用ajax同步加載,而後我試了真能夠,下面就是個人代碼分享出來給你們,可是注意這樣加載出來的js有一個致命的弱點,就是無法再瀏覽器上調試- - !!!!!之後再尋找解決方案吧,先貼代碼:javascript
js主文件importComJs.js:css
** * Created by carlos on 2015/5/19. * QImport 導入幫助函數,能夠很方便的導入指定的js、css文件。可是須要注意的是,這樣導入的js將沒法調試,暫時沒有找到解決方案--! * 使用方法先把此文件引入,必須放在head中的最前面導入, * <script src="../js/importComJs.js" id="QImport"></script> * id必須是QImport,不然無效 * 而後加入 * <script> * QImport.init(customscripts); * </script> * customscripts參數爲:外加的引入文件配置,能夠不填。但填寫必須遵照QImport.IMPORTSCRIPTS的寫法。 * 若是不想手動初始化引入函數,能夠這樣寫: * <script src="../js/importComJs.js" id="QImport" data-auto="true"></script> * 這裏的 data-auto爲true時候纔會自動初始化,不然須要手動初始化。 * 使用上自動初始化,不用擔憂引入順序問題,後面的其餘js、css文件按正常引用就能夠了。 * 注意:importComjs文件必須第一個引入,不然將出現引用找不到的問題。 * 新增屬性: * data-config:自定義配置文件名,默認爲「importConfig.json」 * data-personalconfigname:自定義個性化配置名稱,在配置文件中的「personalscripts」中配置 * 注意:配置加載順序是:importscripts最高、personalscripts其次、customscripts最低。若是引入的次序不對會引發空指針報錯哦^^! */ /** * 同步加載js腳本 * @param id 須要設置的<script>標籤的id * @param url js文件的相對路徑或絕對路徑 * @return {Boolean} 返回是否加載成功,true表明成功,false表明失敗 */ (function(){ QImport = { self:{ obj:function(){ return document.getElementById('QImport'); //獲取script的id,若是項目中實在是有衝突不得不改,那就該這個「QImport」吧! }, auto:function(){ return eval(this.getAttr('data-auto')); //是否開啓自動初始化模式,默認爲false }, config:function(){ return this.getAttr('data-config'); //自定義配置文件名,默認爲「importConfig.json」 }, personal:function(){ return this.getAttr('data-personalconfigname') //自定義個性化配置名稱,在配置文件中的「personalscripts」中配置。 }, src:function(){ return this.getAttr('src'); //此文件位置,很少說 }, getAttr:function(attrName){ var attrValue = undefined; try{ attrValue = this.obj().getAttribute(attrName); } catch(e){} return attrValue; }, relationpath:function(){ var src = this.src(); var re = /^[..\/]*/; return src.match(re)[0]; }, path:function(filename){ var src = this.src(); var temp = src.split('/'); var path = ""; temp.pop(); temp.push(filename); return temp.join('/'); } }, autoinit:function(){ if(this.self.auto()){ this.init(); } }, getpath:function(p){ var path = this.self.relationpath()+p; return path.replace('//','/'); }, init:function(customscripts){ //導入文件的主方法 this.extend(customscripts); var IMPORTSCRIPTS = this.IMPORTSCRIPTS; var head = document.getElementsByTagName("head").item(0); var meta = document.createElement('meta'); //自動添加web手機適應代碼; meta.name = 'viewport'; meta.content = 'width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no'; head.insertBefore(meta, head.childNodes[0]); var re = /^http[s]?:\/\//i; for(var i=0;i<IMPORTSCRIPTS.length;i++){ loadpath = IMPORTSCRIPTS[i].url; if(!re.test(IMPORTSCRIPTS[i].url)){ loadpath = this.getpath(IMPORTSCRIPTS[i].url); } if(IMPORTSCRIPTS[i].type=="script"){ var flag = this.loadJS(loadpath,loadpath,i+1) if(!flag){ alert('loading path:"'+loadpath+'" failed,May be lost "http(s)://"'); } } else if(IMPORTSCRIPTS[i].type=="css"){ var csss = document.createElement('link') csss.href = this.getpath(IMPORTSCRIPTS[i].url); csss.rel = 'stylesheet'; head.insertBefore(csss, head.childNodes[i+1]); } } }, extend:function(customscripts){ //自定義擴展方法,僅適用當前對象 if(!(customscripts instanceof Array)) return; var IMPORTSCRIPTS = this.IMPORTSCRIPTS; for(var i=0;i<customscripts.length;i++){ var flag = false; for(var j=0;j<IMPORTSCRIPTS.length;j++){ if((IMPORTSCRIPTS[j].type==customscripts[i].type)&&(IMPORTSCRIPTS[j].url==customscripts[i].url)){ flag = true; break; } } if(!flag){ this.IMPORTSCRIPTS.push({type:customscripts[i].type,url:customscripts[i].url}); } } }, ajax:function(url){ //ajax原始方法,這裏僅能夠同步請求 var xmlHttp = null; if(window.ActiveXObject)//IE { try { //IE6以及之後版本中可使用 xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { //IE5.5以及之後版本可使用 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } } else if(window.XMLHttpRequest)//Firefox,Opera 8.0+,Safari,Chrome { xmlHttp = new XMLHttpRequest(); } //採用同步加載 xmlHttp.open("GET",url,false); //發送同步請求,若是瀏覽器爲Chrome或Opera,必須發佈後才能運行,否則會報錯 xmlHttp.send(null); //4表明數據發送完畢 if ( xmlHttp.readyState == 4 ){ //0爲訪問的本地,200到300表明訪問服務器成功,304表明沒作修改訪問的是緩存 if((xmlHttp.status >= 200 && xmlHttp.status <300) || xmlHttp.status == 0 || xmlHttp.status == 304){ return xmlHttp.responseText; } else{ return false; } } else{ return false; } }, loadJS:function(id,url,rank){ //加載js文件 var importText = this.ajax(url); if(!importText) return false; var myHead = document.getElementsByTagName("HEAD").item(0); var myScript = document.createElement( "script" ); myScript.language = "javascript"; myScript.type = "text/javascript"; myScript.id = id; try{ //IE8以及如下不支持這種方式,須要經過text屬性來設置 myScript.appendChild(document.createTextNode(importText)); } catch (ex){ myScript.text = importText; } myHead.insertBefore(myScript, myHead.childNodes[rank]); return true; }, template:{ //加載模板文件,如今僅在引入「jquery」的狀況下可用。 parent:this, //父類this引用 _setparent:function(){ //把父類的this賦給子方法的parent this.template.parent = this; }, includeTagName:'include', //引入時候用的標籤:<include url="head.html"></include> init:function(){ this.include(); }, include:function(){ var includes = document.getElementsByTagName(this.includeTagName); for(var i=0;i<includes.length;i++){ var url = includes[i].getAttribute('url'); var includeHtml = this.parent.ajax(url); var parent = includes[i].parentNode; var newEs = this.parseDom(includeHtml); for(var j=0;j<newEs.length;j++){ parent.insertBefore(newEs[j], includes[i]) } } while(true){ if(includes.length==0) break; includes[0].remove(); } }, parseDom:function(str){ var obj = document.createElement('div'); obj.innerHTML = str; return obj.childNodes; } }, initparent:function(){ //子類中想用父類中的方法必須經過此方法初始化如下,還必須引入如template的parent和_setparent this.template._setparent.call(this); }, getimportjson:function(){ //獲取的配置json var configName = this.self.config(); //共用配置 if(configName) this.configname = configName; var configpath = this.self.path(this.configname); var confJsonStr = this.ajax(configpath); if(!confJsonStr){ alert('config file path:"'+configpath+'" can not be loaded'); return; } this.confJson = eval('('+confJsonStr+')'); importarr = this.confJson.importscripts; if(importarr instanceof Array){ this.IMPORTSCRIPTS = this.confJson.importscripts; } this.getpersonalarr(); }, getpersonalarr:function(){ //獲取個性化配置arr var personalConfigName = this.self.personal(); if(!personalConfigName) return; this.personalconfigname = personalConfigName; var personalarr = this.confJson.personalscripts[personalConfigName]; if(personalarr instanceof Array){ this.extend(personalarr) } }, confJson:{}, IMPORTSCRIPTS:[], configname:'importConfig.json' } QImport.getimportjson(); QImport.autoinit(); QImport.initparent(); try{ $(function(){ QImport.template.init(); }); } catch(e){} })();
下面是配置文件,importConfig.json:html
{ importscripts:[ { type: 'script', url: 'js/jquery-1.9.1/jquery-1.9.1.min.js' },{ type: 'script', url: 'js/mui.min.js' },{ type: 'css', url: 'css/mui.min.css' },{ type: 'script', url: 'js/json2.js' } ], personalscripts:{ test:[ { type:'script', url:'js/test.js' } ] } }
注意配置文件必須和導入方法js在同一個路徑底下。java
以上就是我我的封裝的引入js、css的代碼,但願和你們交流下,有什麼問題但願你們能不吝指教!jquery