【问题标题】:Getting notified when the page DOM has loaded (but before window.onload)在页面 DOM 加载时收到通知(但在 window.onload 之前)
【发布时间】:2008-09-15 18:28:43
【问题描述】:

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

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

目前我知道的:

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

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

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

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

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

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

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

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

【问题讨论】:

  • 有这方面的消息吗?这个答案在这里已经存在了 2.5 年......也许浏览器供应商和标准现在更好?
  • 不,虽然 IE9 现在也支持 DOMContentLoaded。所以我们只能坐等

标签: javascript dom


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    【解决方案3】:

    YUI 使用三个测试来做到这一点:对于 Firefox 和最近的 WebKit,有一个 DOMContentLoaded 事件被触发。对于较旧的 Safari,document.readyState 一直在观察,直到它变为“已加载”或“完成”。对于 IE,会创建一个 HTML

    标记并调用“doScroll()”方法,如果 DOM 未准备好,该方法会出错。 YAHOO.util.Event 的源代码显示了特定于 YUI 的代码。在 Event.js 中搜索“doScroll”。

    【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          为什么不这样:

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

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

          【讨论】:

          • 不幸的是,如果我无法控制页面,这个简单的解决方案将不起作用 - 例如在创建将通过
          【解决方案7】:

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

          DomContentLoaded 是您最好的选择。对于 IE-oldies,您仍然需要 polling 技术。

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

          【讨论】:

            【解决方案8】:

            这很好用:

            setTimeout(MyInitFunction, 0);
            

            【讨论】:

            • 不,它没有。从长远来看,这并不可靠。对不起。 :-/
            【解决方案9】:

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

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

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

            等等

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

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

            【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-07-07
            • 2018-08-16
            • 1970-01-01
            • 2022-07-06
            • 1970-01-01
            • 2018-12-07
            • 1970-01-01
            相关资源
            最近更新 更多