关于javascript:如何在没有框架的情况下检查DOM是否准备就绪?

How to check if DOM is ready without a framework?

这个问题在这里和网络上是如此的类似——如何检查dom是否已经加载到了javascript中?但关键是:

  • 不使用jquery等框架;
  • 不知道您的脚本是通过静态放置的标记加载的,还是在DOM加载之后的很长时间内通过其他一些javascript加载的。

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

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


document.readyState属性可用于检查文档是否就绪:

1
2
3
4
5
6
7
8
9
if(document.readyState ==="complete") {
  //Already loaded!
}
else {
  //Add onload or DOMContentLoaded event listeners here: for example,
  window.addEventListener("onload", function () {/* your code here */}, false);
  //or
  //document.addEventListener("DOMContentLoaded", function () {/* code */}, false);
}


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

它在IE中更为复杂。jquery在IE中所做的是通过document.onload事件的备份在文档对象上监视onreadystatechange。document.onload在dom准备就绪之后激发(仅当所有图像都已完成加载时),因此它仅用作backstop,以防早期事件由于某种原因无法工作。

如果你花些时间在谷歌上,你会找到代码来做这个。我认为要做到这一点,最经过审查的代码是在大型框架(如jquery和yui)中,因此,即使我不使用该框架,我也会在它们的源代码中查找技术。

下面是jquery 1.6.2中用于document.ready()的源代码的主要部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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();
        }
    }
},


这适用于所有浏览器,并且简短:

1
2
3
4
5
6
7
8
var execute = function () {
  alert("executing code");  
};

if ( !!(window.addEventListener) )
  window.addEventListener("DOMContentLoaded", execute)
else // MSIE
  window.attachEvent("onload", execute)

如果依赖document.readyState是可以的,那么可以通过轮询快速解决问题:

1
2
3
4
5
6
7
(function() {
    var state = document.readyState;
    if(state === 'interactive' || state === 'complete') {
        // do stuff
    }
    else setTimeout(arguments.callee, 100);
})();


当初始HTML文档完全加载和解析后,不需要等待样式表、图像和子帧完成加载,就会触发DOMContentLoaded事件。好消息是chrome、firefox、ie9、opera和safari同样支持它。

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

NOTE : Internet Explorer 8 supports the readystatechange event, which
can be used to detect when the DOM is ready.


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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

</html>

编辑:用于Vilx的评论

这里有许多onload绑定示例http://jsfiddle.net/utf2n/3/