在 jQuery 的 .ready() 之前执行的非 jQuery .ready() 替代方案,与 DOMContentLoaded 不同
Posted
技术标签:
【中文标题】在 jQuery 的 .ready() 之前执行的非 jQuery .ready() 替代方案,与 DOMContentLoaded 不同【英文标题】:non-jQuery .ready() alternative that executes BEFORE jQuery's .ready(), unlike DOMContentLoaded 【发布时间】:2015-05-29 16:35:13 【问题描述】:我正在制作一个不依赖 jQuery 的插件,为了与各种现有流行的 jQuery 功能和插件很好地配合,必须在到达 DOM 末尾之后执行一个函数,但是不是在之后使用 jQuery .ready()
执行任何稍后排队的操作。
标准的非jQuery .ready()
替代品是document.addEventListener("DOMContentLoaded",function());
。
如果页面具有使用 jQuery .ready()
和 DOMContentLoaded
延迟的功能:
.ready()
s 都按照它们定义的顺序执行
...然后所有DOMContentLoaded
s 执行,按照它们被定义的顺序:
...两者都发生在 interactive
和 complete
文档 readyStates 之间:
document.addEventListener("readystatechange", function () alert(document.readyState); );
document.addEventListener("DOMContentLoaded", function(event) alert(1); );
$(document).ready(function() alert(2); );
document.addEventListener("DOMContentLoaded", function(event) alert(3); );
$(document).ready(function() alert(4); );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
我可以使用什么类似于 document.addEventListener("DOMContentLoaded")
但没有被任何和所有 jQuery .ready()
s 这样的抢占?
为了明确确切的时间,在我的特定情况下,我可以保证这个时间关键代码在任何.ready()
s 排队之前排队,所以与.ready()
附加到同一队列的答案也将解决我的问题,而不仅仅是抢占 all .ready()
s 的答案。但是抢占所有.ready()
s 可能更可取,因为它适用于更广泛的情况。
(对于 jQuery 的 .ready()
的任何清晰简单的解释,无论何时定义,它都会在所有 document.addEventListener("DOMContentLoaded")
之前执行,我无法弄清楚)
【问题讨论】:
我去过!:-)
但我还没有破解 jQuery 如何设法领先于所有 "DOMContentLoaded"
s 的问题,即使它们是在 jQuery 本身之前定义的
【参考方案1】:
它实际上与 .ready() 调用本身无关,它与在您的代码示例之前加载 jQuery 的事实有关。
jQuery 在加载时为 DOMContentLoaded/load 添加了一个事件侦听器,因此当您的代码示例运行时,jQuery 已经添加了一个侦听器。所以它会在你的例子中的听众之前被解雇。
浏览器会执行这些步骤
-
浏览器加载 jquery.js
jQuery 初始化并在 DOMContentLoaded/load 上添加监听器
您的代码运行时会在 DOMContentLoaded 上添加侦听器并添加 .ready() 回调
DOMContentLoaded 被触发
jQuery 的侦听器在其他侦听器之前在队列中,因此它首先被触发
jQuery 依次执行每个 .ready() 回调
队列中的所有其他 DOMContentLoaded 侦听器接下来都会被触发
现在您可以通过在包含 jQuery 之前放置您的 addEventListener 代码来首先调用您的代码
<script>
document.addEventListener("DOMContentLoaded", function(event) alert(1); );
</script>
<script src="jquery.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) alert(3); );
$(document).ready(function() alert(2); );
$(document).ready(function() alert(4); );
</script>
演示
<script>
document.addEventListener("DOMContentLoaded", function(event) alert(1); );
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) alert(3); );
$(document).ready(function() alert(2); );
$(document).ready(function() alert(4); );
</script>
如果您无法控制代码的放置,您可能会很不走运。您可以尝试使用快速执行的间隔计时器(即每毫秒)并检查 dom 是否准备好以及何时执行您的代码。但不能保证它会先被执行。
【讨论】:
好的,所以整个.ready()
队列是DOMContentLoaded
队列中的一项,在加载jQuery 时添加。我现在的问题是,我有一种情况,即使 jQuery 稍后出现在代码中,我的 DOMContentLoaded
s 也会最后出现......我会尝试 inspecting the event listeners
没有原生 js 函数可以为您提供通过 addEventListener 添加的事件侦听器列表。唯一的方法是自己跟踪它们,但这仍然需要您在所有其他人之前加载您的代码,以便您可以跟踪它们。【参考方案2】:
将您的 jqueries 放在文档文件的末尾。它有时会帮助您解决冲突..:D
【讨论】:
是的,不幸的是,它是一个插件,它不能影响使用它的人如何构建他们的 html。事实上,不管 JS 的顺序和位置如何,让我的插件变得健壮是我要解决的问题......【参考方案3】:如果问题解释正确,您可以使用$.holdReady()
$.holdReady(true);
// do stuff
document.addEventListener("DOMContentLoaded"
, function(event) alert(1); );
document.addEventListener("DOMContentLoaded"
, function(event) alert(2); );
$.holdReady(false);
$(document).ready(function() //do stuff when `$.holdReady(false)` is called);
【讨论】:
以上是关于在 jQuery 的 .ready() 之前执行的非 jQuery .ready() 替代方案,与 DOMContentLoaded 不同的主要内容,如果未能解决你的问题,请参考以下文章
JQuery.ready 为时已晚:如何在渲染之前将 CSS 值与 JQuery 一起应用?