【问题标题】:Javascript - How to detect if document has loaded (IE 7/Firefox 3)Javascript - 如何检测文档是否已加载(IE 7/Firefox 3)
【发布时间】:2010-11-01 23:59:42
【问题描述】:

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

【问题讨论】:

  • "我想在文档加载后调用一个函数,但文档可能尚未完成加载,也可能尚未完成。"这不计算。
  • 我相信他的意思是他无法控制他的代码块最初运行的时间,但希望确保在文档完成加载之前不调用 DoStuffFunction()。

标签: javascript events onload addeventlistener


【解决方案1】:
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}

【讨论】:

  • 似乎在最新的 Chrome 中不起作用 document.loaded 始终未定义
  • 这是 2010 年 :)。现在我将使用body.readyState === 'loaded'
【解决方案2】:

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

}

【讨论】:

    【解决方案3】:

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

    在文档加载时返回“正在加载”,在完成解析但仍在加载子资源后返回“交互”,在加载后返回“完成”。 -- document.readyState at Mozilla Developer Network

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

    【讨论】:

    • @costa,如果是document.readyState == "complete",则表示所有内容(包括图片)都已加载完毕。
    • 我正在使用这两个事件和document.readyState 的组合来确保函数在 DOM 被解析之后启动,或者稍后,这取决于它被调用的时间。 interactive readyState有活动吗?
    • 我会使用/loaded|complete/.test(document.readyState)。一些浏览器将document.readyState 设置为“已加载”而不是“完成”。此外,document.readyState 不能确保字体已经加载,没有插件就没有真正的好方法来测试它。
    • document.onreadystatechange 怎么样?如果浏览器支持它,这似乎更精简。 stackoverflow.com/questions/807878/…
    • 我认为最好检查 document.readyState !== "loading" 是否处于“DOM 就绪”状态。这可以防止在 readyState 由于某种原因(在“交互”状态之后)被延迟检查时出现问题。
    【解决方案4】:

    Mozila Firefox 表示 onreadystatechangeDOMContentLoaded 的替代品。

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

    DOMContentLoaded Mozila 的文档中说:

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

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

    【讨论】:

      【解决方案5】:

      试试这个:

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

      【讨论】:

        【解决方案6】:

        我有其他解决方案,我的应用程序需要在创建 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');
        

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

        【讨论】:

          【解决方案7】:

          不需要图书馆。 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;
          

          【讨论】:

          • 完全错过了问题的重点。 init 如果在页面加载后包含您发布的此代码,则将不会运行,这是 OP 的重点:他/她无法控制何时包含他的脚本。 (注意只有setInterval 分支可以工作)
          • 这属于图书馆。与所有其他轮子一样,人们通常会重新发明。
          【解决方案8】:

          如果您真的希望这段代码在 load 时运行,而不是在 domready(即您还需要加载图像),那么不幸的是,ready 函数不适合您。我通常只是做这样的事情:

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

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

          然后你的代码:

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

          (或您偏好框架中的等价物。)我使用此代码为将来的页面进行 javascript 和图像的预缓存。由于我得到的东西根本不用于这个页面,我不希望它优先于快速下载图像。

          可能有更好的方法,但我还没有找到。

          【讨论】:

            【解决方案9】:

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

            类似:

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

            似乎会做你想做的事。

            【讨论】:

            • 如果他想了解 jQuery 是如何以可移植的方式完成的,可以查看 jQuery 的源代码 :-)
            • 如果不清楚,如果ready()文档加载后被调用,传递的函数会立即运行。
            • @Ben Blank:除非在文档加载后包含 jQuery 本身;)
            • @Roatin Marth — 实际上,这也很好用。 (刚刚在 FF8 和 IE8 上使用 jQuery 1.7.1 尝试过。)
            • -1:即使答案有意义,OP 也从未提及 jQuery。仅仅为了准备好文档而使用整个 jQuery 项目实在是太过分了。
            猜你喜欢
            • 2010-11-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-11-30
            • 1970-01-01
            • 1970-01-01
            • 2013-09-08
            • 1970-01-01
            相关资源
            最近更新 更多