我有一个带有DOMContentLoaded
事件处理程序的脚本-
document.addEventListener('DOMContentLoaded', function() {
console.log('Hi');
});
我正在异步加载它-
<script async src=script.js></script>
但是,永远不会调用事件处理程序。如果我同步加载-
<script src=script.js></script>
它工作得很好。
(即使我将DOMContentLoaded
事件更改为load
事件,它也不会被调用。)
怎么回事?无论浏览器如何加载脚本,都应该注册事件处理程序,不是吗?
编辑:它不能在Chrome18.0.1025.11测试版上运行,但在DOMContentLoaded
上,它可以在Firefox11测试版上运行(但在load
上不能)。去想一想。
哦,伟大的JAVASCRIPT和DOM的领主,请指出我的错误!
发布于 2012-02-11 09:50:40
通过异步加载脚本,您告诉浏览器它可以独立于页面的其他部分加载该脚本。这意味着页面可能会完成加载,并可能在加载脚本和注册事件之前触发DOMContentLoaded
。如果发生这种情况,你将错过这个事件(当你注册它的时候,它已经发生了)。
在所有现代浏览器中,您可以测试文档以查看它是否已加载(MDN doc),您可以检查:
if (document.readyState !== "loading")
以查看文档是否已加载。如果是,那就做你自己的事吧。如果不是,则安装事件侦听器。
事实上,作为一个参考源和实现思想,jQuery用它的.ready()
方法做了同样的事情,而且它看起来得到了广泛的支持。当调用.ready()
时,jQuery具有此代码,该代码首先检查文档是否已加载。如果是,它会立即调用ready函数,而不是绑定事件侦听器:
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
return setTimeout( jQuery.ready, 1 );
}
发布于 2015-10-16 06:27:54
这不是最终的答案,但让我明白了为什么在需要修改DOM的脚本中使用异步是不正确的,所以必须等待DOMContentLoaded事件。希望可能是有益的。
发布于 2018-04-25 23:37:39
大多数普通的JS就绪函数都没有考虑在文档加载之后启动DOMContentLoaded
处理程序的场景-这意味着函数永远不会运行。如果在async
外部脚本(<script async src="file.js"></script>
)中使用DOMContentLoaded
,就会发生这种情况。
下面的代码仅在文档的readyState
不是interactive
或complete
时才检查DOMContentLoaded
。
var DOMReady = function(callback) {
document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback);
};
DOMReady(function() {
//DOM ready!
});
如果你也想支持IE:
var DOMReady = function(callback) {
if (document.readyState === "interactive" || document.readyState === "complete") {
callback();
} else if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", callback);
} else if (document.attachEvent) {
document.attachEvent("onreadystatechange", function() {
if (document.readyState != "loading") {
callback();
}
});
}
};
DOMReady(function() {
// DOM ready!
});
https://stackoverflow.com/questions/9237044
复制相似问题