动态包含JavaScript并等待
我试图做的是在Javascript中动态地包含一个或多个js文件。我知道有很多方法可以做到这一点,但我正在寻找一种遵循以下规则的解决方案: 1) 不使用任何JS框架或库(jQuery、Prototype等) 2) 脚本应该停止执行,直到外部js文件被浏览器完全加载和解析 rational behind#2是外部js文件,它将包含在脚本包含之后需要立即使用的函数定义。在我开始调用这些函数之前,浏览器大部分时间都没有时间解析js文件 我不介意使用回调来知道脚本何时完成加载,但是: 1) 我不知道提前动态包含多少脚本,所以我不想也不能编写一堆嵌套回调。我只想知道他们什么时候都装好了 2) 我认为,如果浏览器缓存了JavaScript,那么尝试使用某种“加载”事件来触发回调可能不起作用 编辑我应该从一开始就提到这是一个插件系统,但我想让我的问题/答案足够通用,以便对其他人有所帮助 用户将定义要在阵列中加载的插件动态包含JavaScript并等待,javascript,ajax,Javascript,Ajax,我试图做的是在Javascript中动态地包含一个或多个js文件。我知道有很多方法可以做到这一点,但我正在寻找一种遵循以下规则的解决方案: 1) 不使用任何JS框架或库(jQuery、Prototype等) 2) 脚本应该停止执行,直到外部js文件被浏览器完全加载和解析 rational behind#2是外部js文件,它将包含在脚本包含之后需要立即使用的函数定义。在我开始调用这些函数之前,浏览器大部分时间都没有时间解析js文件 我不介意使用回调来知道脚本何时完成加载,但是: 1) 我不知道提前
plugins = [ 'FooPlugin', 'BarPlugin' ];
然后,我将在数组中循环,并为每个插件加载js脚本:
for(var i = 0; i < plugins.length; i++) {
loadScript('plugins/' + plugins[i] + '.js');
}
我所知道的最简单(也是最可靠)的解决方案就是简单地使用document.write在文档中插入一个新的脚本标记(当然,也可以根据您的需要):
我脑子里有几种可能的方法。我要写的是步骤,不是代码 选项1
怎么样?可以跨浏览器工作,从IE6开始
document.loadScript = function (src, callback) {
function script(src, onload) {
var scriptTag = document.createElement('script');
if (onload) scriptTag.onload = onload;
scriptTag.src = src;
scriptTag.type = 'text/javascript';
return scriptTag;
}
function outer(tag) {
var d = document.createElement('div');
d.appendChild(tag);
return d.innerHTML;
}
if (!(src instanceof Array)) src = [src];
var i, scr,
callbackId = 'dynCall_'+Math.floor(Math.random()*89999+10000);
counter = src.length,
call = function () { if (--counter == 0) callback(); };
if (!document.body) {
window[callbackId] = function () {
delete window[callbackId];
if (callback instanceof Function) callback();
};
for (i=0; i<src.length; i++) document.write(outer(script(src[i])));
document.write('<scr'+'ipt type="text/javascript">'+'window.'+callbackId+'();'+'</scr'+'ipt>');
return;
}
for (i=0; i<src.length; i++) document.body.appendChild(script(src[i], call));
};
document.loadScript=函数(src,回调){
函数脚本(src,onload){
var scriptTag=document.createElement('script');
如果(onload)scriptTag.onload=onload;
scriptTag.src=src;
scriptTag.type='text/javascript';
返回脚本标签;
}
函数外部(标记){
var d=document.createElement('div');
d、 附加子(tag);
返回d.innerHTML;
}
如果(!(src instanceof Array))src=[src];
变量i,scr,
callbackId='dynCall_u'+Math.floor(Math.random()*89999+10000);
计数器=src.length,
call=function(){if(--counter==0)callback();};
如果(!document.body){
窗口[callbackId]=函数(){
删除窗口[callbackId];
if(callback instanceof Function)callback();
};
对于(i=0;idocument.write只是初始页面加载期间的一个可行解决方案。之后任何时候使用它都会覆盖整个页面。问题比这更复杂。解释了动态加载javascript,但这还不够聪明,无法实现脚本何时完成执行。是的,很好;我只有我们两个很久以前,我就在脑海中直接提到了这一点。第二种方法是跨浏览器兼容的?是的,是的。这也是一种很好的模块化方法。我不确定这个答案,所以就把它作为一个注释发布。您是否试过使用AJAX将javascript的内容加载到客户端变量中,然后使用eval()
?由于您必须等待AJAX返回200/OK消息,因此您知道整个脚本都已加载,eval()
在完成整个脚本的运行之前,不应将您踢到下一行。您能确定页面加载期间需要哪些脚本吗?如果是,那么@Paul的解决方案是理想的。否则,您的解决方案将取决于您要支持的浏览器以及脚本是否与您的页面位于同一域中。@steven_desu-不会加载的脚本中的函数/变量最终会在调用eval()的上下文中结束?这意味着它们在使用eval的函数之外不可用。需要明确的是…是scr。
<script type="text/javascript">document.write('<' + 'script src="/assets/js/file.js" type="text/javascript"><\/script>');</script>
Loader.script( [
'./js/jquery/jquery.jmap.js',
'./js/jquery/jquery.getUrlParam.js',
'./js/jquery/jquery.form.js',
'./js/jquery/jquery.gettext.js',
'./js/jquery/jquery.scrollTo.js',
'./js/jquery/jquery.prettydate.js'
], { complete: function() {
// do your thing
}
})
document.loadScript = function (src, callback) {
function script(src, onload) {
var scriptTag = document.createElement('script');
if (onload) scriptTag.onload = onload;
scriptTag.src = src;
scriptTag.type = 'text/javascript';
return scriptTag;
}
function outer(tag) {
var d = document.createElement('div');
d.appendChild(tag);
return d.innerHTML;
}
if (!(src instanceof Array)) src = [src];
var i, scr,
callbackId = 'dynCall_'+Math.floor(Math.random()*89999+10000);
counter = src.length,
call = function () { if (--counter == 0) callback(); };
if (!document.body) {
window[callbackId] = function () {
delete window[callbackId];
if (callback instanceof Function) callback();
};
for (i=0; i<src.length; i++) document.write(outer(script(src[i])));
document.write('<scr'+'ipt type="text/javascript">'+'window.'+callbackId+'();'+'</scr'+'ipt>');
return;
}
for (i=0; i<src.length; i++) document.body.appendChild(script(src[i], call));
};
(function(){document.loadScript=function(src,callback){function script(src,onload){var scriptTag=document.createElement('script');if(onload)scriptTag.onload=onload;scriptTag.src=src;scriptTag.type='text/javascript';return scriptTag}function outer(tag){var d=document.createElement('div');d.appendChild(tag);return d.innerHTML}if(!(src instanceof Array))src=[src];var i,scr,callbackId='dynCall_'+Math.floor(Math.random()*89999+10000);counter=src.length,call=function(){if(--counter==0)callback()};if(!document.body){window[callbackId]=function(){delete window[callbackId];if(callback instanceof Function)callback()};for(i=0;i<src.length;i++)document.write(outer(script(src[i])));document.write('<scr'+'ipt type="text/javascript">'+'window.'+callbackId+'();'+'</scr'+'ipt>');return}for(i=0;i<src.length;i++)document.body.appendChild(script(src[i],call))};document.loadScript.toString=function(){return'function loadScript() { [obfuscated] }'}})();