Javascript-如何检测文档是否已加载(IE 7 / Firefox 3)


163

我想在文档加载后调用一个函数,但是文档可能尚未加载完成。如果确实加载了,那么我就可以调用该函数。如果未加载,则可以附加事件监听器。在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);
    }
}

5
“我想在文档加载后调用一个函数,但是文档可能已经加载或可能尚未完成加载。” 这不会计算。
理查德·西蒙斯(RichardSimões)2009年

7
我相信他的意思是他无法控制最初运行其代码块的时间,但希望确保在文档完成加载之前不会调用DoStuffFunction()。
本·布兰克

Answers:


257

不需要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可以有三种状态:

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

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


3
@costa,如果为document.readyState == "complete",则表示所有内容(包括图像)均已加载。
劳伦特

我正在使用这两个事件的组合,并document.readyState确保该函数在解析DOM之后或以后(取决于调用时间)启动。有互动 活动readyState吗?
托马什Zato -恢复莫妮卡

3
我会用/loaded|complete/.test(document.readyState)。某些浏览器设置document.readyState为“已加载”而不是“完成”。另外,document.readyState不能确保已加载字体,没有插件就没有真正好的方法来测试字体。
瑞安·泰勒

2
document.onreadystatechange呢 如果浏览器支持,这似乎更加简化。stackoverflow.com/questions/807878/...

2
我认为最好检查document.readyState !== "loading"“ DOM ready”状态。如果由于readyState某种原因(在“交互”状态之后)而检查得太晚,这可以防止出现问题。
rnevius

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;

1
正是我想要的-没有jQuery库的jQuery.ready函数。谢谢!
stricjux 2011年

3
完全错过了问题的重点。init如果在页面加载后包含了您发布的代码,则将无法运行,这就是OP的要点:他/她无法控制何时包含他的脚本。(请注意,只有setInterval分支机构才能正常工作)
Roatin Marth 2012年

3
这属于一个库。人们通常会与所有其他轮子一起重新发明。
b01

14

您可能想要使用类似jQuery的工具,这使JS编程更容易。

就像是:

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

似乎会做你所追求的。


2
而且,如果他想看看jQuery如何以一种可移植的方式进行操作,可以在jQuery的源进行检查:-)
Thomas L Holaday

7
如果不清楚,如果文档加载ready()调用,则传递的函数将立即运行。
本·布兰克

2
@Ben Blank:除非加载文档后当然包括jQuery本身,否则;)
Roatin Marth 2012年

@Roatin Marth —实际上,这也很好。(只需在FF8和IE8上使用jQuery 1.7.1进行尝试即可。)
Ben Blank

35
-1:即使答案有意义,OP也从未提及jQuery。仅使用整个jQuery项目来准备文档就太过分了。
marcgg 2013年

8
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}

似乎工作,在最新的Chrome并不document.loaded总是不确定的
Aniket

这是2010年:)。现在,我将使用body.readyState === 'loaded'
Jman,

6

如果您实际上希望此代码在加载时运行,而不是在domready时运行(即,您还需要加载图像),那么很遗憾,ready函数无法为您完成此工作。我通常只是做这样的事情:

包含在文档javascript中(即始终在触发onload之前调用):

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

然后你的代码:

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

(或者在您的首选项框架中,它是等效的。)我使用此代码为将来的页面进行javascript和图像的预缓存。由于我得到的东西根本没有用于此页面,因此我不希望它优先于快速下载图像。

也许有更好的方法,但是我还没有找到它。


4

Mozila Firefox表示,这onreadystatechange是的替代方案DOMContentLoaded

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

DOMContentLoadedMozila的文档中说:

当文档已完全加载和解析时,将触发DOMContentLoaded事件,而无需等待样式表,图像和子帧完成加载(load事件可用于检测已完全加载的页面)。

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


3

上面使用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);

}

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

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');

我知道,它可以在所有浏览器上使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.