85

这个问题就像这里和网络上的无数其他问题一样 - 如何检查 DOM 是否已在 Javascript 中加载?但这里有一个问题:

  • 不使用 jQuery 等框架;
  • 不知道您的脚本是通过静态放置的<script>标签还是在 DOM 加载后很久之后通过其他一些 Javascript 加载的。

这可以或多或少可靠地完成并具有跨浏览器兼容性吗?

补充:让我澄清一下:我正在编写一个独立的 .JS 文件,它可以包含在任意网页中。我想在加载 DOM后执行代码。但我不知道我的脚本将如何包含在内可以通过放置<script>标签(在这种情况下,传统onload或 DOM 就绪解决方案将起作用);或者它可以通过 AJAX 或其他方式加载,在 DOM 已经加载之后很久(所以前面提到的解决方案永远不会触发)。

4

6 回答 6

100

The document.readyState property can be used to check if the document is ready. From MDN:

Values

The readyState of a document can be one of following:

  • loading – The document is still loading.
  • interactive – The document has finished loading and the document has been parsed but sub-resources such as images, stylesheets and frames are still loading.
  • complete – The document and all sub-resources have finished loading. The state indicates that the load event is about to fire.

Code example:

if(document.readyState === "complete") {
    // Fully loaded!
}
else if(document.readyState === "interactive") {
    // DOM ready! Images, frames, and other subresources are still downloading.
}
else {
    // Loading still in progress.
    // To wait for it to complete, add "DOMContentLoaded" or "load" listeners.

    window.addEventListener("DOMContentLoaded", () => {
        // DOM ready! Images, frames, and other subresources are still downloading.
    });

    window.addEventListener("load", () => {
        // Fully loaded!
    });
}
于 2011-11-11T22:54:15.257 回答
10

Firefox、Opera 和基于 Webkit 的浏览器有一个文档级事件DOMContentLoaded,您可以使用document.addEventListener("DOMContentLoaded", fn, false).

IE中比较复杂。jQuery 在 IE 中所做的就是onreadystatechange通过 document.onload 事件的备份来监视特定就绪状态的文档对象。document.onload 在 DOM 准备好之后触发(仅当所有图像都完成加载时),因此它仅用作支持,以防早期事件由于某种原因不起作用。

如果您花一些时间在 Google 上搜索,您会找到执行此操作的代码。我认为最受审查的代码是在像 jQuery 和 YUI 这样的大型框架中,因此,即使我没有使用该框架,我也会在他们的源代码中查找技术。

这是 jQuery 1.6.2 源代码的主要部分document.ready()

bindReady: function() {
    if ( readyList ) {
        return;
    }

    readyList = jQuery._Deferred();

    // 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 );
    }

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

        // A fallback to window.onload, that will always work
        window.addEventListener( "load", jQuery.ready, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent( "onreadystatechange", DOMContentLoaded );

        // A fallback to window.onload, that will always work
        window.attachEvent( "onload", jQuery.ready );

        // If IE and not a frame
        // continually check to see if the document is ready
        var toplevel = false;

        try {
            toplevel = window.frameElement == null;
        } catch(e) {}

        if ( document.documentElement.doScroll && toplevel ) {
            doScrollCheck();
        }
    }
},
于 2011-11-11T22:21:08.860 回答
9

如果依赖document.readyState是可以的,使用轮询的快速而肮脏的解决方案:

(function() {
    var state = document.readyState;
    if(state === 'interactive' || state === 'complete') {
        // do stuff
    }
    else setTimeout(arguments.callee, 100);
})();
于 2011-11-11T23:22:36.003 回答
9

这适用于所有浏览器,并且简洁明了:

var execute = function () {
  alert("executing code");  
};

if ( !!(window.addEventListener) )
  window.addEventListener("DOMContentLoaded", execute)
else // MSIE
  window.attachEvent("onload", execute)
于 2013-04-24T15:50:01.957 回答
5

DOMContentLoaded事件在初始 HTML 文档完全加载和解析后触发,无需等待样式表、图像和子框架完成加载。好在 chrome、firefox、IE9、opera 和 safari 都支持它

document.addEventListener("DOMContentLoaded", function(event) 
{
    console.log("DOM fully loaded and parsed");
}

注意:Internet Explorer 8 支持 readystatechange 事件,可用于检测 DOM 何时准备就绪。

于 2016-05-29T10:25:14.157 回答
3

这是在页面底部运行脚本的一种方法。此外,通过使用 window.onload 您可以等待加载所有图像/脚本。或者您可以简单地将代码放在底部而不等待加载图像。

<html>
<head>
</head>
<body>
</body>
<script language="text/javascript">
  window.onload = (function (oldOnLoad) {
    return function () {
      if (oldOnLoad) { 
        olOnLoad();  //fire old Onload event that was attached if any.
      }
      // your code to run after images/scripts are loaded
    }
  })(window.onload);

  // your code to run after DOM is loaded
</script>
</html>

编辑:对于 Vilx 的评论

这里的许多 onload 绑定是一个示例http://jsfiddle.net/uTF2N/3/

于 2011-11-11T22:13:14.647 回答