美元(文档).JavaScript中的ready等价物



我尝试为jQuery $(document)找到等效的代码。准备好了,发现有一些不同的版本:

版本1:

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

版本2:

document.addEventListener('DOMContentLoaded', fn);

有什么区别?为什么版本1会检查document.readyState?另外,版本1是一个函数,而版本2是一个已执行的语句。那么版本1应该有一个语句吗:

ready(fn);

jQuery的文档有你的问题的答案。

jQuery.ready ():

大多数浏览器以DOMContentLoaded事件的形式提供类似的功能。然而,jQuery的.ready()方法在一个重要和有用的方面有所不同:如果DOM准备好了,并且浏览器在代码调用.ready( handler )之前触发了DOMContentLoaded,函数处理程序仍然会被执行。相反,在事件触发后添加的DOMContentLoaded事件侦听器永远不会执行....

所以你的版本2有上述问题。版本1即使文档已经准备好,也调用传递的函数。

不同的是,如果您添加了对ready的调用,那么即使在DOMContentLoaded触发之后执行脚本(更多信息请参阅document.readyState),第一个也可以工作。第二个不会,因为事件只触发一次,所以如果脚本在此之后执行,fn将永远不会被调用。

那么,在事件已经触发之后,脚本如何执行呢?基本上,如果它是动态添加的,而不是作为文档初始HTML的一部分。下面是几个例子:

  • 在文档加载后添加的script元素。
  • 一个通过动态import()而不是静态import加载的模块。

可能还有其他人。

版本1是一个函数,而版本2是一个已执行的语句。那么版本1应该有一个语句吗:

ready(fn);

是的,绝对正确。


我应该注意,你不需要如果 您可以控制脚本如何包含在页面中。(所以,你在库中确实需要它,但很少在应用程序/页面中。)如果您控制脚本如何包含在页面中,并且希望代码在构建DOM之后运行,那么可以使用以下几种方法(IMHO,按照最佳实践的顺序):

  • 在脚本上使用type="module"使其成为一个模块。模块在DOM构建完成之前不会执行(它们是自动延迟的,即使是内联模块;
  • script标签上使用defer(仅适用于引用文件的src脚本标签,而不是内联脚本)。延迟脚本直到DOM构建完成才执行。
  • script标签放在文档的末尾,就在结束</body>标签之前。

如果你做任何这些事情,没有必要使用ready(jQuery的或那些在你的问题)。

最新更新