$(document).ready()的非jQuery等效项是什么?


444

什么是非jQuery等效项$(document).ready()


4
如果你想重现jQuery的$(document).ready()事件,而无需使用任何图书馆,给看看这个:stackoverflow.com/questions/1795089/...
CMS

@OP:退房临的JavaScript技术的89页的香草JavaScript实现的$(document).ready()- books.google.com/...。它还使用了addEvent由Dean Edwards编写的事件绑定抽象,其代码也在书中:)
Russ Cam 2010年

Answers:


75

好的事情$(document).ready()是它会先触发window.onload。加载功能会一直等到所有内容加载完毕,包括外部资产和图像。$(document).ready但是,当DOM树完成并且可以进行操作时会触发。如果您想在没有jQuery的情况下实现DOM就绪,则可以签入此库。有人ready从jQuery中提取了一部分。它的大小不一,您可能会发现它有用:

随时可以在Google Code中使用


4
DomReady代码网络!通过github上的@CMS:github.com/cms/domready/network
Kzqai 2011年

44
这不会回答问题,也不会显示任何非jQuery代码。它是怎么得到这么多投票的?
Daniel W.

3
@DanielW。因为它简单实用。我们大多数人来这里都是为了寻找一种方法来确保DOM已准备好被JavaScript代码使用。
abarazal

是的,但我们当中有些人是来这里寻求实际答案的。
Slbox

611

从ECMA上可以完美运行

document.addEventListener("DOMContentLoaded", function() {
  // code...
});

之所以window.onload不等于JQuery,$(document).ready是因为$(document).readywindow.onload检查包括外部资产和图像在内的所有元素时,它仅等待DOM树。

编辑:添加了IE8和更旧的等效版本,这要感谢Jan Derk的观察。您可以通过以下链接在MDN 阅读此代码的源代码:

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "interactive") {
        // Initialize your application or run some code.
    }
}

除了以外,还有其他选择"interactive"。有关详细信息,请参见MDN链接。


同意本杰明。您不能简单地使用attachEvent。例如,在Chrome中,您得到:未捕获的TypeError:document.attachEvent不是一个函数。使用Jan Derk的链接答案。
Manuel Arwed Schmidt

9
如果调用此脚本时文档已经加载怎么办?什么都不会发生:(
oriadam '16

8
@Deerloper Nope,刚刚在Chrome控制台上尝试过-没有任何反应:立即document.addEventListener("DOMContentLoaded",function(){console.log(123)})尝试
oriadam

2
浏览器中对DOMContentLoaded的支持:caniuse.com/domcontentloaded
Guillaume

1
@elliottregan是的,我删除了注释以避免污染该线程,我建议大家都做同样的事情:)如果需要的话,让一个注释指出注释。因为那是额外的,因为它超出了OC问题的范围
sospedra 19-4-25

43

我整理了一点

domready.js

(function(exports, d) {
  function domReady(fn, context) {

    function onReady(event) {
      d.removeEventListener("DOMContentLoaded", onReady);
      fn.call(context || exports, event);
    }

    function onReadyIe(event) {
      if (d.readyState === "complete") {
        d.detachEvent("onreadystatechange", onReadyIe);
        fn.call(context || exports, event);
      }
    }

    d.addEventListener && d.addEventListener("DOMContentLoaded", onReady) ||
    d.attachEvent      && d.attachEvent("onreadystatechange", onReadyIe);
  }

  exports.domReady = domReady;
})(window, document);

如何使用它

<script src="domready.js"></script>
<script>
  domReady(function(event) {
    alert("dom is ready!");
  });
</script>

您还可以通过传递第二个参数来更改回调运行的上下文

function init(event) {
  alert("check the console");
  this.log(event);
}

domReady(init, console);

2
谢谢。我喜欢它向后兼容的事实。向前迈进并不意味着只剩下一些幸运的人。不幸的是,无法使用现代浏览器(无论出于何种原因)...
CO

28

现在到了2018年,这是一种快速简单的方法。

这将添加一个事件侦听器,但是如果它已经被触发,我们将检查dom处于就绪状态还是已完成。这可能在子资源(图像,样式表,框架等)加载完成之前或之后触发。

function domReady(fn) {
  // If we're early to the party
  document.addEventListener("DOMContentLoaded", fn);
  // If late; I mean on time.
  if (document.readyState === "interactive" || document.readyState === "complete" ) {
    fn();
  }
}

domReady(() => console.log("DOM is ready, come and get it!"));

其他读物


更新资料

这是一些使用我编写的标准ES6 Import&Export的快速实用程序帮助程序,其中还包括TypeScript。也许我可以解决这些问题,使其成为一个可以作为依赖项安装到项目中的快速库。

的JavaScript

export const domReady = (callBack) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

打字稿

export const domReady = (callBack: () => void) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack: () => void) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

承诺

export const domReady = new Promise(resolve => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', resolve);
  }
  else {
    resolve();
  }
});

export const windowReady = new Promise(resolve => {
  if (document.readyState === 'complete') {
    resolve();
  }
  else {
    window.addEventListener('load', resolve);
  }
});

16

根据http://youmightnotneedjquery.com/#ready的说法,仍然可以与IE8一起使用的很好的替代方法是

function ready(fn) {
  if (document.readyState != 'loading') {
    fn();
  } else if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', fn);
  } else {
    document.attachEvent('onreadystatechange', function() {
      if (document.readyState != 'loading')
        fn();
    });
  }
}

// test
window.ready(function() {
    alert('it works');
});

改进:我个人还将检查的类型fn是否为函数。正如@elliottregan所建议的,使用后请删除事件监听器。

我之所以回答这个问题很晚,是因为我在寻找这个答案,但是在这里找不到。我认为这是最好的解决方案。


1
是的,这是我认为的最佳答案。易于阅读,即使DOM已经加载,它也可以执行代码。我唯一要添加的是在事件触发后删除事件监听器。
elliottregan

14

超过90%的浏览器都支持基于标准的DOMContentLoaded替换,但IE8不支持(所以下面的代码被JQuery用于浏览器支持)

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

jQuery的本机功能比window.onload复杂得多,如下所示。

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            jQuery.ready();
        }, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent("onreadystatechange", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

            try {
                // If IE is used, use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                document.documentElement.doScroll("left");
            } catch( error ) {
                setTimeout( arguments.callee, 0 );
                return;
            }

            // and execute any waiting functions
            jQuery.ready();
        })();
    }

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}

1
新的jQuery放弃了对旧版浏览器的支持,现在它们仅具有DOMContentLoadedload事件,使用addEventListener,并且首先触发删除两个侦听器,因此不会触发两次。
jcubic

8

在普通的JavaScript中,没有库?这是一个错误。$只是一个标识符,除非您定义它,否则是未定义的。

jQuery将$其定义为自己的“所有对象”(也称为“对象”,jQuery因此您可以在不与其他库冲突的情况下使用它)。如果您不使用jQuery(或其他定义它的库),则$不会被定义。

还是您在问普通JavaScript中的等效内容是什么?在这种情况下,您可能需要window.onload,它并不完全等效,但是是在原始JavaScript中接近相同效果的最快,最简单的方法。


39
对于这个答案的许多反对者(以及下面的其他答案):提出此问题时,它只是说:“ javascript中的$(document).ready()是什么?不是jquery。这是什么?” 听起来他在问没有加载jQuery的纯原始JavaScript是什么意思。在我的回答中,我尝试回答该问题,并给出最简单的简单答案,即纯jQuery的jQuery和其他库(以防万一)。请注意,所有其他上下文都是由其他人添加的,他们是在猜测问题的所在,而不是原始的发帖人。
Brian Campbell 2013年

5

在最近的浏览器中,最简单的方法是使用适当的GlobalEventHandlersonDOMContentLoadedonloadonloadeddata(...)

onDOMContentLoaded = (function(){ console.log("DOM ready!") })()

onload = (function(){ console.log("Page fully loaded!") })()

onloadeddata = (function(){ console.log("Data loaded!") })()

当初始HTML文档已完全加载和解析而没有等待样式表,图像和子帧完成加载时,将触发DOMContentLoaded事件。完全不同的事件加载应仅用于检测页面已满。在DOMContentLoaded更合适的地方使用负载是一个非常普遍的错误,因此请务必谨慎。

https://developer.mozilla.org/zh-CN/docs/Web/Events/DOMContentLoaded

使用的函数是IIFE,在这种情况下非常有用,因为它在准备就绪时会触发自身:

https://zh.wikipedia.org/wiki/立即调用功能_表达式

将它放在任何脚本的末尾显然更合适。

在ES6中,我们还可以将其编写为箭头函数:

onload = (() => { console.log("ES6 page fully loaded!") })()

最好是使用DOM元素,我们可以等待触发箭头IIFE的任何变量准备就绪。

行为将相同,但对内存的影响较小。

footer = (() => { console.log("Footer loaded!") })()
<div id="footer">

在许多情况下,至少在我的浏览器中,文档对象也会在就绪时触发。语法非常好,但是需要进一步测试兼容性。

document=(()=>{    /*Ready*/   })()

可以在DOM完成元素加载之后触发IIFE吗?
CTS_AE

当然,它只是闭包中的一个函数,一个匿名函数。
NVRM

0

正文onLoad也可以是一种替代方法:

<html>
<head><title>Body onLoad Exmaple</title>

<script type="text/javascript">
    function window_onload() {
        //do something
    }
</script>

</head>
<body onLoad="window_onload()">

</body>
</html>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.