2008-09-15 65 views
7

我知道有一些方法可以在页面主体加载时得到通知(在所有加载的图像和第三方资源之前,这会触发window.onload事件),但每个浏览器都不同。当页面DOM已经加载(但在window.onload之前)时得到通知

有没有一种在所有浏览器上做到这一点的权威方法?

到目前为止,我所知道的:

  • DOMContentLoaded:在Mozilla,Opera 9中和最新WebKits。这涉及到向事件添加侦听器:

    document.addEventListener(“DOMContentLoaded”,[init function],false);

  • 延期脚本:在IE上,您可以发出带有@defer属性的SCRIPT标签,该标签只能在关闭BODY标签后才能加载。

  • 轮询:在其他浏览器,你可以继续投票,但有甚至轮询一个标准的东西,或者你需要在每个浏览器做不同的事情?

我希望能够不使用document.write或外部文件。

这可以简单地通过jQuery来完成:

$(document).ready(function() { ... }) 

但是,我正在写一个JS库,不能指望jQuery的总是在那里。

+0

有什么消息对此有何看法?这个答案在这里坐了2.5年...也许浏览器供应商和标准现在更好地加快速度? – Akku 2011-05-12 14:08:30

+0

不,尽管IE9现在也支持DOMContentLoaded。所以我们只是坐等IE9浏览器的市场份额低于1%。 – 2013-03-11 14:25:26

回答

8

有没有检查时,DOM是准备跨浏览器的方法 - 这就是为什么有像jQuery库,不兼容的抽象掉讨厌的小位。

Mozilla,Opera和现代WebKit支持DOMContentLoaded事件。 IE和Safari需要像滚动窗口或检查样式表一样的奇怪黑客。血腥细节包含在jQuery的bindReady()函数中。

+1

`bindReady`:https://github.com/jquery/jquery/blob/master/src/core.js – XP1 2012-02-03 11:32:38

1

只要从jQuery获取相关的代码片段,John Resig就已经在jQuery中介绍了这个问题的大部分基础。

-2

这工作得很好:

setTimeout(MyInitFunction, 0); 
+0

不,它不。这远远不可靠。抱歉。: -/ – 2008-10-30 02:32:40

2

YUI使用三​​种测试来做到这一点:对于Firefox和最近的WebKit,有一个DOMContentLoaded事件被触发。对于较旧的Safari,document.readyState会一直观看,直到它变成“加载”或“完成”。对于IE,HTML <P>标记被创建并且调用“doScroll()”方法,如果DOM没有准备好,它应该会出错。 YAHOO.util.Event的来源显示了YUI特定的代码。在Event.js中搜索“doScroll”。

2

使用像jQuery这样的库会为您节省无数小时的浏览器不一致。

在这种情况下使用jQuery你可以

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

如果你好奇,你可以在源看看,看看它是如何做,而是这个时代我不认为任何人不当图书馆作家为你完成所有痛苦的工作时,应该重塑这一轮。

3

我发现此页面,其中显示了一个紧凑的自包含解决方案。这似乎在每一个浏览器中运行,并且对如何解释:

http://www.kryogenix.org/days/2007/09/26/shortloaded

+1

它看起来像是从这个代码派生的:http://javascript.nwbox.com/ContentLoaded /。我在各种浏览器中尝试了这个原始代码,它对我来说非常棒。 – arlomedia 2012-04-09 23:07:35

-2

使用的setTimeout可以工作得很好,虽然当它执行的是最高的浏览器。如果您通过零作为超时时间,浏览器将在事情“解决”时执行。

关于这件事的好处是,你可以有很多这样的事情,而且不必担心链接onLoad事件。

setTimeout(myFunction, 0); 
setTimeout(anotherFunction, 0); 
setTimeout(function(){ doSomething ...}, 0); 

他们将在文档加载完成后,或者如果您设置一个文件被加载后,你的脚本运行完毕后,他们将都跑。

它们运行的​​顺序不确定,并且可能在浏览器之间改变。所以你不能指望在anotherFunction之前运行myFunction

+0

重点在于尽可能早地执行JS,但并不是在所有页面的DOM都到位之前执行 - 这将允许用户检查DOM,而不必等待可能加载的图像缓慢。 – levik 2008-09-16 14:57:42

0

为什么不这样:

<body> 
    <!-- various content --> 
    <script type="text/javascript"> 
    <!-- 
    myInit(); 
    --> 
    </script> 
</body> 

如果我理解正确的事情,myInit是谈婚论嫁,只要浏览器中点击它的网页,这是一体的最后一件事执行。

0

您正在寻找的花式交叉浏览器解决方案....并不存在...(想象一个拥挤的人说'aahhhh ....')的声音。

DomContentLoaded只是你最好的拍摄。 IE-oldies仍然需要polling技术。

  1. 尝试使用addEventListener;
  2. 如果不可用(IE明显),检查帧;
  3. 如果不是帧,滚动直到没有错误被抛出(轮询);
  4. 如果一帧,使用IE事件document.onreadystatechange;
  5. 对于其他不支持的浏览器,请使用旧的document.onload事件。

我发现在javascript.info下面的代码示例,您可以使用支付所有的浏览器:

function bindReady(handler){ 

    var called = false 

    function ready() { 
     if (called) return 
     called = true 
     handler() 
    } 

    if (document.addEventListener) { // native event 
     document.addEventListener("DOMContentLoaded", ready, false) 
    } else if (document.attachEvent) { // IE 

     try { 
      var isFrame = window.frameElement != null 
     } catch(e) {} 

     // IE, the document is not inside a frame 
     if (document.documentElement.doScroll && !isFrame) { 
      function tryScroll(){ 
       if (called) return 
       try { 
        document.documentElement.doScroll("left") 
        ready() 
       } catch(e) { 
        setTimeout(tryScroll, 10) 
       } 
      } 
      tryScroll() 
     } 

     // IE, the document is inside a frame 
     document.attachEvent("onreadystatechange", function(){ 
      if (document.readyState === "complete") { 
       ready() 
      } 
     }) 
    } 

    // Old browsers 
    if (window.addEventListener) 
     window.addEventListener('load', ready, false) 
    else if (window.attachEvent) 
     window.attachEvent('onload', ready) 
    else { 
     var fn = window.onload // very old browser, copy old onload 
     window.onload = function() { // replace by new onload and call the old one 
      fn && fn() 
      ready() 
     } 
    } 
} 
相关问题