关于在javascript里面加载其它的js文件的问题可能不少人都遇到过,但不少朋友可能并不知道怎么判断咱们要加载的js文件是否加载完成,若是没有加载完成咱们就调用文件里面的函数是不会成功的。本文讲解怎么在js中加载其它js文件并在加载完成后执行回调函数。javascript
咱们能够动态的建立 <script> 元素,而后经过更改它的 src 属性来加载脚本,可是怎么知道这个脚本文件加载完成了呢,由于咱们有些函数须要在脚本加载完成生效后才能开始执行。 通过对网络上资源的搜索,我发如今 IE 浏览器中可使用 <script> 元素的 onreadystatechange 来监控加载状态的改变,并经过判断它的 readyState 是 loaded 或 complete 来判断脚本是否加载完成。而非 IE 浏览器可使用 onload 来直接判断脚本是否加载完成。html
一个简单的实现过程看上去是下面这样的:java
//IE下:
var script = document.createElement("script"); script.setAttribute("type","text/javascript"); script.onreadystatechange = function() { if(this.readyState == "loaded" || this.readyState == "complete"){ alert("加载成功啦!"); } } script.setAttribute("src",scripts[i]); //Opera、FF、Chrome等: var script = document.createElement("script"); script.setAttribute("type","text/javascript"); script.onload = function() { alert("加载成功啦!"); } script.setAttribute("src",scripts[i]);
原理很简单,根据这两个简单的原理,咱们进行一些修改,我把改为了两个函数,分别是串行加载和并行加载脚本。 jquery
当传一个包含多个JS文件路径的数组时,串行加载函数从第一个脚本文件加载开始,每加载成功一个便开始加载下一个脚本文件,所有加载完成后执行回调函数。而并行加载是一开始便加载所有的脚本文件,也就是他们从同一点开始加载,当所有加载完成后,执行回调函数。ajax
通过测试,这两个函数兼容目前的全部主流浏览器。api
/** * 串联加载指定的脚本 * 串联加载[异步]逐个加载,每一个加载完成后加载下一个 * 所有加载完成后执行回调 * @param array|string 指定的脚本们 * @param function 成功后回调的函数 * @return array 全部生成的脚本元素对象数组 */ function seriesLoadScripts(scripts,callback) { if(typeof(scripts) != "object") var scripts = [scripts]; var HEAD = document.getElementsByTagName("head").item(0) || document.documentElement; var s = new Array(), last = scripts.length - 1, recursiveLoad = function(i) { //递归 s[i] = document.createElement("script"); s[i].setAttribute("type","text/javascript"); s[i].onload = s[i].onreadystatechange = function() { //Attach handlers for all browsers if(!/*@cc_on!@*/0 || this.readyState == "loaded" || this.readyState == "complete") { this.onload = this.onreadystatechange = null; this.parentNode.removeChild(this); if(i != last) recursiveLoad(i + 1); else if(typeof(callback) == "function") callback(); } } s[i].setAttribute("src",scripts[i]); HEAD.appendChild(s[i]); }; recursiveLoad(0); } /** * 并联加载指定的脚本 * 并联加载[同步]同时加载,无论上个是否加载完成,直接加载所有 * 所有加载完成后执行回调 * @param array|string 指定的脚本们 * @param function 成功后回调的函数 * @return array 全部生成的脚本元素对象数组 */ function parallelLoadScripts(scripts,callback) { if(typeof(scripts) != "object") var scripts = [scripts]; var HEAD = document.getElementsByTagName("head").item(0) || document.documentElement, s = new Array(), loaded = 0; for(var i=0; i<scripts.length; i++) { s[i] = document.createElement("script"); s[i].setAttribute("type","text/javascript"); s[i].onload = s[i].onreadystatechange = function() { //Attach handlers for all browsers if(!/*@cc_on!@*/0 || this.readyState == "loaded" || this.readyState == "complete") { loaded++; this.onload = this.onreadystatechange = null; this.parentNode.removeChild(this); if(loaded == scripts.length && typeof(callback) == "function") callback(); } }; s[i].setAttribute("src",scripts[i]); HEAD.appendChild(s[i]); } }
在这里是把 <script> 标签动态的插入到页面中的 <head> 标签内部,而且加载完成后标签元素会被自动移除。 细心的你还会发现,这里使用了一种称做条件编译的方法做为表达式(!/*@cc_on!@*/0)来判断是否非 IE 浏览器,关于条件编译并非本文的重点,有兴趣的您能够上网查找相关资料进行学习。跨域
这两个函数的使用方法: 这里咱们声明了一个数组变量,里面包含了两个远程的JS文件地址(固然 <script> 标签调用脚本是支持跨域的):数组
var scripts = [ "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", "http://wellstyled.com/files/jquery.debug/jquery.debug.js" ]; //这两个文件分别是 jQuery 1.4.的库文件和 jQuery Debug 插件 //而后你可使用下面的方法调用并在成功后执行回调了。 seriesLoadScripts(scripts,function(){ /* debug = new $.debug({ posTo : { x:'right', y:'bottom' }, width: '480px', height: '50%', itemDivider : '<hr>', listDOM : 'all' }); */ alert('脚本加载完成啦'); });
这里使用的是串联加载的函数,固然你也可使用并联加载函数,这能够根据状况使用,建议每下一个脚本对上一个脚本有依赖性的使用串联加载,不然使用并联,由于原理上并联要比串联快那么些。浏览器