关于javascript:’$(document).ready()’的非jQuery等价物是什么?

What is the non-jQuery equivalent of '$(document).ready()'?

什么是的非jQuery等价物?


这非常适合ECMA

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

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

编辑:由于Jan Derk的观察,添加了IE8和更旧的等价物。您可以在此链接上阅读MDN上此代码的来源:

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

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


关于$(document).ready()的好处是它在window.onload之前触发。加载功能等待所有内容加载,包括外部资源和图像。但是,$(document).ready在DOM树完成并且可以被操作时触发。如果你想准备好DOM,没有jQuery,你可以检查这个库。有人从jQuery中提取了ready部分。它很好很小,你可能会发现它很有用:

已完全使用Google Code


我放在一起的小东西

domready.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(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);

如何使用它

1
2
3
4
5
<script src="domready.js">

  domReady(function(event) {
    alert("dom is ready!");
  });

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

1
2
3
4
5
6
function init(event) {
  alert("check the console");
  this.log(event);
}

domReady(init, console);


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

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

1
2
3
4
5
6
7
8
9
10
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!"));

附加读物

  • https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

    • 检查装载是否已完成
  • https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState

更新

这里有一些使用标准ES6 Import&amp; amp;的快速实用助手。 导出我写的也包括TypeScript。 也许我可以绕过这些快速库,可以作为依赖项安装到项目中。

JavaScript的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
  }
}

打字稿

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
  }
}

承诺

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
  }
});

有一个基于标准的替换,DOMContentLoaded支持超过90%以上的浏览器,但不支持IE8(所以下面的代码使用JQuery来支持浏览器):

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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 );
}


根据http://youmightnotneedjquery.com/#ready,一个仍然适用于IE8的好替代品是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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的类型是否是一个函数。

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


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

jQuery将$定义为它自己的"所有对象"(也称为jQuery,因此您可以使用它而不会与其他库发生冲突)。如果您不使用jQuery(或其他定义它的库),则不会定义$

或者你在问普通JavaScript中的等价物是什么?在这种情况下,您可能需要window.onload,这并不完全等效,但它是在vanilla JavaScript中接近相同效果的最快捷,最简单的方法。


最近浏览器中最简单的方法是使用适当的GlobalEventHandlers,onDOMContentLoaded,onload,onloadeddata(...)

1
2
3
4
5
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/en-US/docs/Web/Events/DOMContentLoaded

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

https://en.wikipedia.org/wiki/Immediately-invoked_function_expression

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

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

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

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

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

1
footer = (() => { console.log("Footer loaded!") })()
1
 

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

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


身体onLoad也可以替代:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<head>Body onLoad Exmaple

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


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

</body>
</html>