我已将我的 javascript 拆分为不同的文件。我想防止 javascript 文件被加载两次。我怎样才能做到这一点?
6 回答
下面根据js文件的路径测试一下是否包含了脚本:
function isScriptAlreadyIncluded(src){
var scripts = document.getElementsByTagName("script");
for(var i = 0; i < scripts.length; i++)
if(scripts[i].getAttribute('src') == src) return true;
return false;
}
它适用于所有未通过 AJAX 加载的脚本,但如果您正在运行 jsonp 代码,您可能需要对其进行修改。
不要将它们包括两次。毕竟,是你在做包含。
但是,如果您动态地执行这些包含,您可以检查脚本是否设置了某些全局函数或对象。例如,如果我在文件中有以下脚本:
Foo = function () {};
然后我像这样包含它:
<script src="../foo.js"></script>
在浏览器解析该脚本标记之前,Foo
是undefined
. 处理完标签后,Foo
是一个Function
. 您可以使用一些基于此的逻辑来确定是否应该包含某些文件。
有时 js 文件是通过其他方式加载的(例如通过 js)。
这时候window.performance
可以派上用场。我们可以检查加载script
的资源,而不是像其他答案中建议的那样检查标签,方法是:
let resources = performance.getEntries()
.filter(e => e.entryType === 'resource')
.map(e => e.name);
if (resources.indexOf("//domain.com/path/to/script.js") === -1) {
// Script was not yet loaded.
}
现在的window.performance
浏览器兼容性还不错:
https ://caniuse.com/mdn-api_performance_getentries
如果我们想同时检查script
标签(对于 DOM 中的所有脚本标签,包括可能尚未加载的脚本的 URL)和window.resources
(对于到目前为止加载的所有脚本,包括通过js),我们可以把它放在一个函数中:
function is_script_already_included(src){
const found_in_resources = performance.getEntries()
.filter(e => e.entryType === 'resource')
.map(e => e.name)
.indexOf(src) !== -1;
const found_in_script_tags = document.querySelectorAll(`script[src*="${src}"]`).length > 0;
return found_in_resources || found_in_script_tags;
}
我已经使用在每个动态加载的脚本底部添加的通用自调用函数解决了这个问题。
首先 - 通过在我的基本文件或将始终加载的脚本中声明一个新的空数组,即我的案例 index.php 中的主页
var scriptsLoaded = new Array();
然后在加载的脚本末尾添加一个自执行函数:
(function () { scriptsLoaded.push( 'this_script_name.js' ) })();
使用这种方法,scriptsLoaded 数组中的任何文件名都应该只引用已经完全加载的脚本。只需检查此数组即可指示是否已加载脚本,该脚本也可用作检查是否为所需脚本执行加载样式函数
不使用任何框架(据我所知),您只能通过检查全局范围内的某个变量是否已被声明来做到这一点。
var include1 = true;
你可以在里面声明一个变量include1.js
,然后做类似的事情
if (window.include1 !== true) {
// load file dynamically
}
您需要手动跟踪并确保。UweB 的建议也行得通。
您还可以查看 Require.js,它可以帮助您组织文件。