150

我正在尝试按顺序加载一组脚本,但onload事件没有为我触发。

var脚本=[“//cdnjs.cloudflare.com/ajax/libs/less.js/1.3.3/less.min.js”,“//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0-rc.3/handlebars/min.js”,MK.host+“/templates/templates.js”];函数loadScripts(脚本){var script=scripts.shift();var el=document.createElement('script');el.src=脚本;el.onload=函数(脚本){console.log(脚本+“已加载!”);if(scripts.length){loadScripts(脚本);}其他{console.log(“运行应用程序”);MK.init();}};$body.append(el);}loadScripts(脚本);

我猜当使用jQuery将元素附加到DOM时,像el.onload这样的本地事件不会触发。如果我使用本机document.body.appendChild(el)然后它会按预期开火。

1

3个答案

重置为默认值
198

您应该设置型钢混凝土属性之后这个空载事件,例如:

el.onload=函数(){//。。。el.src=脚本;

您还应该将脚本附加到DOM之前连接空载事件:

$body.append(el);el.onload=函数(){//。。。el.src=脚本;

记住你需要检查再结晶用于IE支持。如果您正在使用jQuery,您也可以尝试获取脚本()方法:http://api.jquery.com/jquery.getScript/

13
  • 15
    这实际上并不能解决问题。但如果我只使用document.body.appendChild(el)而不是$(“body”).append(el);然后onload事件按预期触发。
    – 香菜
    评论 2013年4月26日7:37
  • 50
    你能帮我理解为什么订购很重要吗?
    – 香菜
    评论 2013年4月26日8:19
  • 15
    @David为什么不将元素附加到最后,如建议的那样html5rocks.com/en/tutorials/speed/script-loading? 这将使您添加事件侦听器并设置型钢混凝土无关紧要。 评论 2015年2月25日7:58
  • 9
    我很好奇:为什么在设置空载型钢混凝土属性? 评论 2017年2月21日0:12
  • 15
    如果脚本是缓存的,那么一旦添加src,就会加载该项,并且onload不会启动。在src之前添加onload将确保为缓存脚本触发onload。 评论 2019年11月25日17:38
16

我遇到了一个类似的问题,试图测试页面上是否已经存在jQuery,如果不强制加载,则执行一个函数。我尝试了@David Hellsing的变通方法,但没有机会满足我的需求。事实上空载指令立即进行评估,然后$在这个函数中还无法使用(是的,“$不是函数。”^^)。

因此,我提到这篇文章:https://developer.mozilla.org/fr/docs/Web/Events/load并将事件侦听器附加到我的脚本对象。

var script=document.createElement('script');script.type=“text/javascript”;script.addEventListener(“加载”,函数(事件){console.log(“已加载脚本:)”);onjqloaded();//实际上,您的填充脚本()函数});script.src=“https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js";document.getElementsByTagName('head')[0].appendChild(script);

根据我的需要,它现在很好用。希望这能帮助他人:)

1
1

按顺序加载脚本的工作方式(即等待一个脚本加载完毕,然后再加载另一个脚本,等等…)

以下脚本将添加到html页面:

<script type=“text/javascript”>document.addEventListener(“DOMContentLoaded”,(event)=>{函数fn(src){return new Promise(resolve=>{//Promise已启动const script=document.createElement(“script”);//创建<script>标记//script.async=true不是必需的,因为使用了Promisescript.onload=解析;//承诺将解决加载事件script.setAttribute(“src”,src);//将设置srs=“链接到此处的源文件”document.getElementsByTagName('body')[0].appendChild(script);//将创建的<script>标记附加到<body>});}const url=[//脚本标记的顺序“/script1.js”,“/script2.js”,“/script3.js”];Promise.resolve(fn(url[0]))//等待url[0得到解析,然后.then(()=>fn(url[1]))//调用并等待url[1]解析,然后.then(()=>fn(url[2]))//调用url[2]});</script>

返回每个结果很重要“.然后”使用"() =>"这叫做链传动:

始终返回结果,否则回调将无法捕获前一个承诺的结果(使用箭头函数,()=>x是()=>{return x;}的缩写)

加载的html页面上的结果:

<body><!-- 您的html--><script src=“/script1.js”><script src=“/script2.js”><script src=“/script3.js”></body>

chrome开发工具

编辑02.05.2024

下面是一个使用IIFE、异步和动态import()的非常简单的解决方案

<script type=“text/javascript”>(异步()=>{等待导入(“/script1.js”)等待导入(“/script2.js”)等待导入(“/script3.js”)})()</script>

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.