要记住的一件事是,当您创建多个<script>
标签时,您无法保证它们的加载顺序,并且取决于它们的构建方式 - 它们通常会在加载后立即开始处理。
因此,如果您在 CDN 中包含一个本地文件和一个文件,例如:
<script type="text/javascript"
src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js">
</script>
<script type="text/javascript" src="/js/my_script.js"></script>
您必须考虑到 CDN 文件的交付速度通常比托管文件快得多。在上述情况下,这可能是一件好事 - 因为jQuery
在您的脚本之前加载到页面上可能是理想的 - 但是如果您正在加载不同的 3rd 方脚本,这可能依赖于您的脚本的 DOM 中存在的某些元素负责创建,您的脚本可能无法及时创建它们。
想象一下这个场景:
<script type="text/javascript" src="https://someurl/somelib.js">
// This script parses the DOM and applies alterations to certain items
</script>
<script type="text/javascript" src="/js/my_script.js">
// This script creates the DOM elements the other script is supposed to alter
</script>
仅当本地文件 , 首先加载时,您的页面才会起作用/js/my_script.js
- 这不太可能,因为其他文件是从专用 CDN 提供的。
当两个文件都在本地提供时,情况会更糟,例如:
<script type="text/javascript" src="/js/my_relied_upon_script.js"></script>
<script type="text/javascript" src="/js/my_reliant_script.js"></script>
在这种情况下,这完全取决于您的本地 Web 服务器如何处理 HTTP 请求,以确定以什么顺序发生的事情。
所以 - 解决方案:
1) 让你的脚本都等待document
'onready
事件触发。因为此事件仅在文档完全加载后发生(包括完全加载其元素所需的任何其他 HTTP 请求,例如脚本、图像等) - 您可以保证脚本至少会等到完整的 DOM加载。
2) 使下级脚本等待触发事件。
使用 jQuery,一个示例可能类似于以下内容:
// Script #1
$(document).bind('ready', function () {
$('#NeedsBackground').css({ background: 'url(/gfx/bg.png)' });
var $wrapper = $('<div />').addClass('wrapper');
$('#NeedsWrapper').wrap($wrapper);
// Here's the magic that enforces loading.
$(document).trigger('Script1Finished');
});
// Script #2
$(document).bind('Script1Finished', function () {
$('.wrapper').css({ border: '1px solid #000' });
});
现在 - 请记住,上述转换是相当糟糕的,而不是您想要做的事情(例如内联 CSS 等,通常) - 但他们举了一个例子。因为Script #2
要求.wrapper
元素在运行之前存在,所以需要确保它在发生之后Script #1
发生。
在这种情况下,我们通过trigger
在文档上设置一个自定义事件来实现这一点,然后我们可以响应该事件 - 我们仅在 DOM 处于正确状态后触发该事件。