繁体   English   中英

如何知道窗口“加载”事件是否已经触发

[英]How to know if window "load" event was fired already

我正在编写一个 Javascript 脚本。 该脚本可能会异步加载(AMD 格式)。

在这个脚本中,在window.load事件被触发之前,我不想做任何重要的事情。 所以我听窗口“加载”事件。

但是如果脚本是在 window.load 事件之后加载的……我怎么知道window.load已经被触发了?

当然我不想在任何其他脚本中添加一些东西(它们都是异步加载的,问题是一样的):)

编辑 :

想象一个完全没有 Javascript 的 HTML 文档。

比有人在这个文档中插入一个标签,这个脚本标签加载我的 Javascript 文件。

这将执行我的脚本。

这个脚本如何知道 window.load 是否已经被触发?

没有 jQuery,在我之前的 HTML 文档中没有任何脚本。

有可能知道吗??

我找到了window.document.readystate属性。 我猜这个属性是针对文档“就绪”事件,而不是针对窗口“加载”。 窗口“加载”事件有类似的东西吗?

最简单的解决方案可能是检查document.readyState == 'complete' ,请参阅http://www.w3schools.com/jsref/prop_doc_readystate.asp

快速回答

要快速回答问题的标题:

document.readyState === 'complete'

更深层次的例子

如果您想在窗口加载时调用代码,下面是一个很好的帮手,同时仍然处理在代码运行时窗口可能已经加载的情况。

 function winLoad(callback) { if (document.readyState === 'complete') { callback(); } else { window.addEventListener("load", callback); } } winLoad(function() { console.log('Window is loaded'); });

注意:此处的代码片段实际上不在同一个窗口上下文中运行,因此document.readyState === 'complete'在您运行它时实际上评估为false 如果您现在为此窗口将相同的内容放入控制台,它应该评估为真。

另请参阅'$(document).ready()' 的非 jQuery 等价物是什么?


通过评论处理来自@IgorBykov 的边缘案例

Igor 在评论中提出了一个有趣的问题,下面的代码可以尝试在尽力超时的情况下处理该问题。

问题是document.readyState可以在load事件触发之前complete 我不确定这可能会导致什么潜在问题。

关于流程和事件触发的一些文档

Complete: The state indicates that the load event is about to fire.

给出了一个事件触发的实例,即:

  1. 就绪状态: interactive
  2. 事件触发: DOMContentLoaded
  3. 就绪状态: complete
  4. 事件触发: load

load触发之前, readyState可能会在短时间内complete 我不确定您在此期间可能会遇到什么问题。

下面的代码注册了load事件监听器,并设置了一个超时来检查readyState 默认情况下,它会在检查readyState之前等待 200 毫秒。 如果load事件在timeout之前触发,我们确保防止再次触发回调。 如果我们到达timeout结束并且load没有被触发,我们检查readyState并确保避免load事件可能在以后触发的情况。

根据您要完成的任务,您可能无论如何都需要运行load回调(删除if (!called) {检查)。 在您的回调中,您可能希望将潜在代码包装在 try/catch 语句中,或者检查您可以控制执行的内容,以便当它调用两次时,它仅在您期望的一切可用时才执行工作。

 function winLoad(callback, timeout = 200) { let called = false; window.addEventListener("load", () => { if (!called) { called = true; callback(); } }); setTimeout(() => { if (!called && document.readyState === 'complete') { called = true; callback(); } }, timeout); } winLoad(function() { console.log('Window is loaded'); });

浏览器导航性能loadEventEnd 指标可用于确定是否触发了加载事件:

let navData = window.performance.getEntriesByType("navigation");
if (navData.length > 0 && navData[0].loadEventEnd > 0)
{
    console.log('Document is loaded');
} else {
    console.log('Document is not loaded');
}

这是我的答案:

小提琴

window.addEventListener("load", function () {
    window.loaded = true;
});

function logLoaded() {
    console.log("loaded");
}

(function listen () {
    if (window.loaded) {
        logLoaded();
    } else {
        console.log("notLoaded");
        window.setTimeout(listen, 50);
    }
})();

您可以在此处阅读addEventListener()及其兼容性(它是ECMAScript 5规范的新增内容)。 这是未来做事的新“首选”方式。

你可以阅读有关立即调用函数表达式(IIFE)(交替,自我援引匿名函数或立即调用匿名函数) 这里

编辑:这是StackOverflow上的一个很好的答案:

如何在没有框架的情况下检查DOM是否准备就绪?

如果您特别想知道DOM加载事件是否已触发,请在DOM“load”事件处理程序中设置一个全局变量,然后在加载新代码时检查它是否存在。

// in 'load' event handler
window.domLoadEventFired = true;

// in code you are loading asynchronously
if (typeof window.domLoadEventFired !== undefined) {
    // ...
}

如果你不想使用 jQuery,它使用的逻辑是:

if( !document.body )
    setTimeout( checkAgain, 1 );

因此,在 windows 加载事件和检查文档的 body 属性是否可用之间,您可以检查 DOM 是否准备好

基于@CTS_AE 的方法,我为以下环境制定了一个解决方案:

  • window.addEventListener('load', activateMyFunction);
  • window.addEventListener('DOMContentLoaded', activateMyFunction);

不工作。

它需要单个字符替换(例如,从

window.addEventListener('load', activateMyFunction);

window_addEventListener('load', activateMyFunction);)

函数window_addEventListener()如下所示:

const window_addEventListener = (eventName, callback, useCapture = false) => {

  if ((document.readyState === 'interactive') || (document.readyState === 'complete'))   {

    callback();
  }
}

简易方法:

window.onload = (event) => {
  console.log('page is fully loaded');
};

您可以从这里的资源中找到其他方法。

覆盖window.load怎么样?

window._load = window.load;
window.load = function(){
  window.loaded = true;
  window._load();
}

然后检查

if (window.loaded != undefined && window.loaded == true){
    //do stuff
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM