首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >未调用DOMContentLoaded或load事件处理程序的异步加载脚本?

未调用DOMContentLoaded或load事件处理程序的异步加载脚本?
EN

Stack Overflow用户
提问于 2012-02-11 09:32:39
回答 4查看 24.2K关注 0票数 42

我有一个带有DOMContentLoaded事件处理程序的脚本-

代码语言:javascript
复制
document.addEventListener('DOMContentLoaded', function() {
    console.log('Hi');
});

我正在异步加载它-

代码语言:javascript
复制
<script async src=script.js></script>

但是,永远不会调用事件处理程序。如果我同步加载-

代码语言:javascript
复制
<script src=script.js></script>

它工作得很好。

(即使我将DOMContentLoaded事件更改为load事件,它也不会被调用。)

怎么回事?无论浏览器如何加载脚本,都应该注册事件处理程序,不是吗?

编辑:它不能在Chrome18.0.1025.11测试版上运行,但在DOMContentLoaded上,它可以在Firefox11测试版上运行(但在load上不能)。去想一想。

哦,伟大的JAVASCRIPT和DOM的领主,请指出我的错误!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-02-11 09:50:40

通过异步加载脚本,您告诉浏览器它可以独立于页面的其他部分加载该脚本。这意味着页面可能会完成加载,并可能在加载脚本和注册事件之前触发DOMContentLoaded。如果发生这种情况,你将错过这个事件(当你注册它的时候,它已经发生了)。

在所有现代浏览器中,您可以测试文档以查看它是否已加载(MDN doc),您可以检查:

代码语言:javascript
复制
if (document.readyState !== "loading")

以查看文档是否已加载。如果是,那就做你自己的事吧。如果不是,则安装事件侦听器。

事实上,作为一个参考源和实现思想,jQuery用它的.ready()方法做了同样的事情,而且它看起来得到了广泛的支持。当调用.ready()时,jQuery具有此代码,该代码首先检查文档是否已加载。如果是,它会立即调用ready函数,而不是绑定事件侦听器:

代码语言:javascript
复制
// 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 );
}
票数 72
EN

Stack Overflow用户

发布于 2015-10-16 06:27:54

这不是最终的答案,但让我明白了为什么在需要修改DOM的脚本中使用异步是不正确的,所以必须等待DOMContentLoaded事件。希望可能是有益的。

(来源:Running Your Code at the Right Time from kirupa.com)

票数 28
EN

Stack Overflow用户

发布于 2018-04-25 23:37:39

大多数普通的JS就绪函数都没有考虑在文档加载之后启动DOMContentLoaded处理程序的场景-这意味着函数永远不会运行。如果在async外部脚本(<script async src="file.js"></script>)中使用DOMContentLoaded,就会发生这种情况。

下面的代码仅在文档的readyState不是interactivecomplete时才检查DOMContentLoaded

代码语言:javascript
复制
var DOMReady = function(callback) {
  document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback);
};
DOMReady(function() {
  //DOM ready!
});

如果你也想支持IE:

代码语言:javascript
复制
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!
});
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9237044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档