Javascript domready?

IT技术 javascript dom-events
2021-01-28 00:39:07

我知道我可以使用原型或 jQuery 等不同的框架将函数附加到window.onload,但这不是我想要的。

我需要类似的东西,.readyState以便我可以做这样的事情:

if(document.isReady){
  var id = document.getElem ...
}

除了使用框架的功能之外,还有其他方法吗?

6个回答

编辑:随着 2018 年的到来,我认为可以安全地聆听该DOMContentLoaded事件。

function fireOnReady() { /* ... */ }
if (document.readyState === 'complete') {
    fireOnReady();
} else {
    document.addEventListener("DOMContentLoaded", fireOnReady);
}

请注意,该事件只会在您的页面加载时触发一次如果您必须支持非常旧的浏览器,请查看我在下面汇总的超轻量级脚本。



仅供历史参考:



jQuery 有一个名为 isReady 的未公开属性,它在内部用于确定 DOM 就绪事件是否已触发:

if($.isReady) {
    // DOM is ready
} else {
    // DOM is not yet ready
}

我从 1.5.2 开始回到 1.3.2 并且该属性在那里。虽然没有记录,但我想说您可以在 jQuery 的未来版本中依赖此属性。 编辑:一年后 - v1.7.2,他们仍在使用$.isReady- 仍然没有记录,所以请自担风险使用。升级时要小心。

编辑: v1.9,他们仍在使用$.isReady- 仍然没有记录

编辑: v2.0,所有它的“主要”变化,仍然使用$.isReady- 仍然没有记录

编辑: v3.x 仍然使用$.isReady- 仍然没有记录

编辑:正如几个人所指出的,上述内容并没有真正回答问题。所以我刚刚创建了一个迷你 DOM 就绪代码段,它的灵感来自达斯汀迪亚兹的更小的 DOM 就绪代码段Dustin 创建了一种简洁的方法来检查文档 readyState 与类似的内容:

if( !/in/.test(document.readyState) ) {
    // document is ready
} else {
    // document is NOT ready
}

这样做的原因是浏览器有 3 种加载状态:“加载”、“交互”和“完成” (较旧的 WebKit 也使用“加载”,但您不必再担心)您会注意到“loading”和“interactive”都包含文本“in”...所以如果在 中找到字符串“in” document.readyState,那么我们知道我们还没有准备好。

@et al - 这是我对 SO 的最早答案之一,我的方式并不明智。感谢那些指出我短视的人,我早就更新了我的答案以包含一个无框架的解决方案。
2021-03-17 00:39:07
不知道为什么投反对票。我解释说这是无证的。在 jQuery 的未来版本中调试这个问题将非常简单,它是那些自描述变量之一,永远不会通过“这个有一个更好的名字”测试,因此可能永远不会被重命名。无论如何......我希望人们能解释反对票。
2021-03-29 00:39:07
这不能回答问题(OP 不想使用框架)。但是,它确实为标记为该问题的“完全重复”的问题提供了一个很好的答案(来自我的 +1)。 stackoverflow.com/questions/8373910/...
2021-03-31 00:39:07
要求是在不使用框架的情况下准备 dom。你的例子解决了这个问题,但使用了一个框架。这应该是询问如何使用 JQuery 准备 dom 的不同问题的一部分,但不应该是当前问题的解决方案。不要为了解决另一个问题而投票。只有在解决当前问题时才会投票。
2021-03-31 00:39:07
Upvoted- 不回答这个问题,但回答了很多人的问题。
2021-04-05 00:39:07

虽然我通常主张除非必要,否则避免使用框架,但我会说在这种情况下使用框架是完全没问题的。这是jQuery:

$(function () {
    // do stuff after DOM has loaded
});

请注意,它与window.onload事件不同,因为onload在加载其他资源(图像等)之后首先执行。我在示例中使用的代码将在 DOM 完成加载时执行,即当完整的 HTML 结构可用时(不一定在图像、CSS 等可用时。)

如果你想要一个可检查的变量,你可以在就绪函数中设置一个:

var documentIsReady = false;
$(function () { documentIsReady = true; });

当然,如果您只想检查 DOM-ready,您可以找到比 jQuery 更轻量级的库。但是在不同浏览器行为非常不同的情况下使用库(这是一种这样的情况。)

使用DOMAssistant 库中的一些代码,制作您自己的“DOM 已准备好”功能应该不会太难:

var domLoaded = function (callback) {
    /* Internet Explorer */
    /*@cc_on
    @if (@_win32 || @_win64)
        document.write('<script id="ieScriptLoad" defer src="//:"><\/script>');
        document.getElementById('ieScriptLoad').onreadystatechange = function() {
            if (this.readyState == 'complete') {
                callback();
            }
        };
    @end @*/
    /* Mozilla, Chrome, Opera */
    if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', callback, false);
    }
    /* Safari, iCab, Konqueror */
    if (/KHTML|WebKit|iCab/i.test(navigator.userAgent)) {
        var DOMLoadTimer = setInterval(function () {
            if (/loaded|complete/i.test(document.readyState)) {
                callback();
                clearInterval(DOMLoadTimer);
            }
        }, 10);
    }
    /* Other web browsers */
    window.onload = callback;
};

未经测试,但它应该可以工作。我从 DOMAssistant 简化了它,因为 DOMAssistant 允许多个回调并检查以确保您不能两次添加相同的函数等。

这段代码对我有用!除非我必须使用,else if否则 Firefox 会触发两次。
2021-03-23 00:39:07
好的,我从 DOMAssistant 添加了一些简化代码,您可以尝试一下。根据他们的网站,它应该适用于所有主要浏览器。domassistant.com/documentation/DOMAssistantLoad-module.php
2021-03-28 00:39:07
我的代码callback最多会调用两次(因为window.onload应该在所有浏览器中执行。)在处理事件时,检查是否callback已经被调用并返回(这是 DOMAssistant 所做的,但我删除了那部分。)
2021-03-28 00:39:07
window.onload不考虑实际值的情况下更改值可能会在其他脚本的代码中产生意外行为。我们也不能调用domLoaded两次,因为只会使用最后一个。
2021-04-03 00:39:07
这是我从框架中唯一需要的东西,它必须提供的所有其他东西,我不需要,所以如果可能的话,我宁愿在这种情况下不使用框架,否则我会使用 jquery
2021-04-09 00:39:07

自从提出这个问题以来的 5 年里,DOMContentLoaded 已经成为一个普遍支持的事件,你可以直接使用它。

document.addEventListener('DOMContentLoaded', function() {
    //.. do stuff ..
}, false);
我刚刚准备好自己对 DOMContentLoaded 发表评论。既然这里没有任何异议,我认为这是正确的方法吗?
2021-03-16 00:39:07
为什么在人们已经对 addEventListener() 发表评论一年后才发布此消息。您没有添加任何您之前的其他答案已经完成的内容。
2021-03-18 00:39:07
每个现代浏览器都支持caniuse.com/#search=DOMContentLoaded
2021-03-27 00:39:07
好吧,抱歉帕特里克,我知道我似乎故意以与您相同的方式重新回答这个问题,以窃取您的网点,但老实说我没有看到您的答案。我当时滚动浏览并认为这很有趣,没有人指出这不再是需要 3rd 方代码的问题。我认为,这仍然是我的答案中人们赞成的部分 - 现在普遍支持这一点。
2021-04-06 00:39:07

我已经更新了DOMAssistant 库的代码,它对我来说很好用

var domReady = (function (){
  var arrDomReadyCallBacks = [] ;
  function excuteDomReadyCallBacks(){
       for (var i=0; i < arrDomReadyCallBacks.length; i++) {
         arrDomReadyCallBacks[i]();
       }
       arrDomReadyCallBacks = [] ;
  }

  return function (callback){
    arrDomReadyCallBacks.push(callback);
     /* Mozilla, Chrome, Opera */
      if (document.addEventListener ) {
          document.addEventListener('DOMContentLoaded', excuteDomReadyCallBacks, false);
      }
    /* Safari, iCab, Konqueror */
    if (/KHTML|WebKit|iCab/i.test(navigator.userAgent)) {
        browserTypeSet = true ;
        var DOMLoadTimer = setInterval(function () {
            if (/loaded|complete/i.test(document.readyState)) {
                //callback();
                excuteDomReadyCallBacks();
                clearInterval(DOMLoadTimer);
            }
        }, 10);
    }
    /* Other web browsers */

    window.onload = excuteDomReadyCallBacks;
}
})()
为什么投反对票?代码使用 ie 8、firefox 和 chrome 进行测试。
2021-03-12 00:39:07
您的示例是 Rube Goldberg 机器。请记住在编写 KISS 方法时。有一种简单的单衬解决方案来解决这个问题,而无需额外的处理。请添加更多文档,说明为什么需要您的解决方案而不是更简单的单行解决方案。没有文档的代码片段不会得到很多支持。
2021-04-01 00:39:07

看看微软的这个演示。-> http://ie.microsoft.com/testdrive/HTML5/DOMContentLoaded/Default.html 这是允许您在 DOM 上运行 JS 准备好的代码的要点......

(function () {
    function load2(){
        // put whatever you need to load on DOM ready in here
        document.getElementById("but3").addEventListener("click", doMore, false);
    }
    if (window.addEventListener) {
        window.addEventListener('DOMContentLoaded', load2, false);
    } else {
        window.attachEvent('onload', load2);
    }
} ());

这是演示的一些 javascript 源代码.. http://ie.microsoft.com/testdrive/Includes/Script/ReturnAndShareControls.js

它运作良好。很好!!...在谷歌浏览器和 IE 9 上。

您不需要addEventListener('DOMContentLoaded', load2, false)DOMContentLoaded末尾的 false没有要遍历的父项。
2021-03-21 00:39:07
@banderson623 抱歉,我太久没有使用帖子中的代码了,无法很好地回忆起来。也许浏览器已针对您建议的更改进行了更新。
2021-03-24 00:39:07
我相信这应该是document.addEventListener(...window
2021-04-03 00:39:07