【问题标题】:non-jQuery .ready() alternative that executes BEFORE jQuery's .ready(), unlike DOMContentLoaded在 jQuery 的 .ready() 之前执行的非 jQuery .ready() 替代方案,与 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 本身之前定义的

标签: javascript jquery execution


【解决方案1】:

它实际上与 .ready() 调用本身无关,它与在您的代码示例之前加载 jQuery 的事实有关。

jQuery 在加载时为 DOMContentLoaded/load 添加了一个事件侦听器,因此当您的代码示例运行时,jQuery 已经添加了一个侦听器。所以它会在你的例子中的听众之前被解雇。

浏览器会执行这些步骤

  1. 浏览器加载 jquery.js
  2. jQuery 初始化并在 DOMContentLoaded/load 上添加监听器
  3. 您的代码运行时会在 DOMContentLoaded 上添加侦听器并添加 .ready() 回调
  4. DOMContentLoaded 被触发
  5. jQuery 的侦听器在其他侦听器之前在队列中,因此它首先被触发
  6. jQuery 依次执行每个 .ready() 回调
  7. 队列中的所有其他 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});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多