js插件動態加載js、css解決方案

  最近由於工做須要作了一個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

相關文章
相關標籤/搜索