在页面DOM加载时(但在window.onload之前)收到通知

时间:2008-09-15 18:28:44

标签: javascript 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始终存在。

9 个答案:

答案 0 :(得分:8)

没有跨浏览器方法来检查DOM何时就绪 - 这就是为什么像jQuery这样的库存在,以抽象出令人讨厌的一些不兼容性。

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

答案 1 :(得分:3)

我找到了这个页面,它显示了一个紧凑的独立解决方案。它似乎适用于每个浏览器,并解释如何:

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

答案 2 :(得分:2)

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

答案 3 :(得分:2)

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

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

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

如果你很好奇,你可以看看来源,看看它是如何完成的,但是在这个时代我不认为当图书馆作家完成所有痛苦的工作时,任何人都应该重新发明这个轮子。你。

答案 4 :(得分:1)

只需从jQuery获取相关代码,John Resig已经在jQuery中涵盖了这个问题的大部分基础。

答案 5 :(得分:0)

为什么不这样:

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

如果我理解正确的话,一旦浏览器在页面中点击它,myInit就会被执行,这是身体中的最后一件事。

答案 6 :(得分:0)

你正在寻找的奇特的crossbrowser解决方案....不存在......(想象一下大人群的声音'aahhhh ......'。

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

  1. 尝试使用addEventListener;
  2. 如果不可用(显然是IE),请检查框架;
  3. 如果不是框架,滚动直到没有错误被抛出(轮询);
  4. 如果是框架,请使用IE event document.onreadystatechange;
  5. 对于其他不支持的浏览器,请使用旧的document.onload事件。
  6. 我在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()
            }
        }
    }
    

答案 7 :(得分:-2)

这非常有效:

setTimeout(MyInitFunction, 0);

答案 8 :(得分:-2)

使用setTimeout可以很好地工作,尽管它的执行取决于浏览器。如果您将超时时间传递为​​零,则浏览器将在事情“已确定”时执行。

关于这一点的好处是你可以拥有其中许多,并且不必担心链接加载事件。

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

它们将在文档加载完毕后全部运行,或者如果在加载文档后设置一个文档,它们将在脚本运行完毕后运行。

他们运行的订单未确定,可以在浏览器之间更改。因此,您不能指望在myFunction之前运行anotherFunction