在 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 延迟的功能:

所有 jQuery .ready()s 都按照它们定义的顺序执行 ...然后所有DOMContentLoadeds 执行,按照它们被定义的顺序:

...两者都发生在 interactivecomplete 文档 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 稍后出现在代码中,我的 DOMContentLoadeds 也会最后出现......我会尝试 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怎么判断页面加载完全

jQuery.ready()

jQuery中ready与load事件的区别

JQuery.ready 为时已晚:如何在渲染之前将 CSS 值与 JQuery 一起应用?

jquery.ready可以在文档加载后尽快执行对文档的操作

为啥我不能使用 onClick 在 jQuery $(document).ready 函数中执行函数?