167

我想在文档加载后调用一个函数,但文档可能尚未完成加载,也可能尚未完成。如果它确实加载了,那么我可以调用该函数。如果它没有加载,那么我可以附加一个事件监听器。在 onload 已经触发后,我无法添加事件监听器,因为它不会被调用。那么如何检查文档是否已加载?我尝试了下面的代码,但它并不完全有效。有任何想法吗?

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if (body && body.readyState == 'loaded') {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}
4

9 回答 9

264

不需要 galambalazs 提到的所有代码。在纯 JavaScript 中跨浏览器的方法是简单地测试document.readyState

if (document.readyState === "complete") { init(); }

这也是 jQuery 的做法。

根据 JavaScript 的加载位置,这可以在一个区间内完成:

var readyStateCheckInterval = setInterval(function() {
    if (document.readyState === "complete") {
        clearInterval(readyStateCheckInterval);
        init();
    }
}, 10);

其实document.readyState可以有三种状态:

在文档加载时返回“正在加载”,在完成解析但仍在加载子资源后返回“交互”,在加载后返回“完成”。-- Mozilla 开发者网络上的 document.readyState

因此,如果您只需要准备好 DOM,请检查document.readyState === "interactive". 如果您需要准备好整个页面,包括图像,请检查document.readyState === "complete".

于 2011-08-17T05:57:49.857 回答
32

不需要图书馆。jQuery 使用这个脚本有一段时间了,顺便说一句。

http://dean.edwards.name/weblog/2006/06/again/

// Dean Edwards/Matthias Miller/John Resig

function init() {
  // quit if this function has already been called
  if (arguments.callee.done) return;

  // flag this function so we don't do the same thing twice
  arguments.callee.done = true;

  // kill the timer
  if (_timer) clearInterval(_timer);

  // do stuff
};

/* for Mozilla/Opera9 */
if (document.addEventListener) {
  document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
  var script = document.getElementById("__ie_onload");
  script.onreadystatechange = function() {
    if (this.readyState == "complete") {
      init(); // call the onload handler
    }
  };
/*@end @*/

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
  var _timer = setInterval(function() {
    if (/loaded|complete/.test(document.readyState)) {
      init(); // call the onload handler
    }
  }, 10);
}

/* for other browsers */
window.onload = init;
于 2010-06-29T20:34:07.210 回答
14

您可能想要使用 jQuery 之类的东西,它使 JS 编程更容易。

就像是:

$(document).ready(function(){
   // Your code here
});

似乎会做你所追求的。

于 2009-06-11T01:16:29.323 回答
9
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}
于 2010-11-17T13:36:34.603 回答
6

If you actually want this code to run at load, not at domready (ie you need the images to be loaded as well), then unfortunately the ready function doesn't do it for you. I generally just do something like this:

Include in document javascript (ie always called before onload fired):

var pageisloaded=0;
window.addEvent('load',function(){
 pageisloaded=1;
});

Then your code:

if (pageisloaded) {
 DoStuffFunction();
} else {
 window.addEvent('load',DoStuffFunction);
}

(Or the equivalent in your framework of preference.) I use this code to do precaching of javascript and images for future pages. Since the stuff I'm getting isn't used for this page at all, I don't want it to take precedence over the speedy download of images.

There may be a better way, but I've yet to find it.

于 2009-08-21T06:03:35.300 回答
4

上面的 JQuery 是最简单和最常用的方法。但是,您可以使用纯 javascript,但尝试在头部定义此脚本,以便在开始时读取它。您正在寻找的是window.onload事件。

下面是我创建的用于运行计数器的简单脚本。然后计数器在 10 次迭代后停止

window.onload=function()
{
    var counter = 0;
    var interval1 = setInterval(function()
    { 
        document.getElementById("div1").textContent=counter;
        counter++; 
        if(counter==10)
        {
            clearInterval(interval1);
        }
    },1000);

}
于 2012-04-11T06:47:13.773 回答
4

Mozilla Firefox 说这onreadystatechangeDOMContentLoaded.

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "complete") {
        initApplication();
    }
}

DOMContentLoadedMozila 的文档中说:

DOMContentLoaded 事件在文档完全加载和解析后触发,无需等待样式表、图像和子框架完成加载(加载事件可用于检测完全加载的页面)。

我认为load事件应该用于完整的文档+资源加载。

于 2014-07-16T11:27:36.430 回答
2

尝试这个:

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if ((body && body.readyState == 'loaded') || (body &&  body.readyState == 'complete') ) {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload',DoStuffFunction);
    }
}
于 2013-12-10T13:44:33.210 回答
1

我有其他解决方案,我的应用程序需要在创建 MyApp 的新对象时启动,所以它看起来像:

function MyApp(objId){
     this.init=function(){
        //.........
     }
     this.run=function(){
          if(!document || !document.body || !window[objId]){
              window.setTimeout(objId+".run();",100);
              return;
          }
          this.init();
     };
     this.run();
}
//and i am starting it 
var app=new MyApp('app');

它适用于所有浏览器,我知道。

于 2013-06-05T07:33:57.377 回答