7

我知道有一些方法可以在页面正文加载时获得通知(在所有图像和第 3 方资源加载触发window.onload事件之前),但对于每个浏览器来说都是不同的。

是否有明确的方法可以在所有浏览器上执行此操作?

到目前为止,我知道:

  • DOMContentLoaded:在 Mozilla、Opera 9 和最新的 WebKits 上。这涉及向事件添加侦听器:

    document.addEventListener("DOMContentLoaded", [初始化函数], false );

  • 延迟脚本:在 IE 上,您可以发出带有 @defer 属性的 SCRIPT 标记,该标记仅在 BODY 标记关闭后才会可靠地加载。

  • 轮询:在其他浏览器上,您可以继续进行轮询,但是是否有标准的事情可以轮询,或者您需要在每个浏览器上做不同的事情?

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

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

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

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

4

9 回答 9

8

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

Mozilla、Opera 和现代 WebKit 支持该DOMContentLoaded活动。IE 和 Safari 需要一些奇怪的技巧,比如滚动窗口或检查样式表。血淋淋的细节包含在 jQuery 的bindReady()函数中。

于 2008-09-15T18:40:52.987 回答
3

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

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

于 2008-09-15T21:27:08.703 回答
2

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

于 2008-09-15T18:45:43.897 回答
2

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

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

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

如果您好奇,您可以查看源代码以了解它是如何完成的,但是在这个时代,当图书馆作者为您完成所有痛苦的工作时,我认为没有人应该重新发明这个轮子。

于 2008-09-15T19:50:20.153 回答
1

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

于 2008-09-15T18:32:15.363 回答
0

为什么不这样:

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

如果我理解正确,myInit 将在浏览器在页面中点击它时立即执行,这是正文中的最后一件事。

于 2008-09-16T10:37:11.767 回答
0

您正在寻找的花哨的跨浏览器解决方案......不存在......(想象一大群人说“啊啊啊......”的声音)。

DomContentLoaded是您最好的选择。您仍然需要pollingIE-oldies 的技术。

  1. 尝试使用 addEventListener;
  2. 如果不可用(显然是 IE),请检查框架;
  3. 如果不是帧,则滚动直到没有抛出错误(轮询);
  4. 如果是frame,使用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()
        }
    }
}
于 2013-03-11T12:15:07.860 回答
-2

这很好用:

setTimeout(MyInitFunction, 0);
于 2008-09-15T18:35:11.223 回答
-2

使用 setTimeout 可以很好地工作,尽管它何时执行取决于浏览器。如果您通过零作为超时时间,浏览器将在事情“解决”时执行。

这样做的好处是您可以拥有许多,而不必担心链接 onLoad 事件。

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

等等

它们都将在文档加载完成后运行,或者如果您在文档加载后设置了一个,它们将在您的脚本完成运行后运行。

它们运行的​​顺序是不确定的,并且可以在浏览器之间改变。因此,例如,您不能指望在myFunction之前运行anotherFunction

于 2008-09-16T09:10:47.920 回答