jquery - window.onload 在 Firefox 中的 jQuery document.ready 之前触发
问题描述
我创建了一个显示问题的 Codepen:https ://codepen.io/samuelg0rd0n/pen/ExVGQEV
在 Chrome 中,它会在窗口加载事件之前正确触发 DOMContentLoaded 事件和 jQuery 文档就绪事件。但是,在 Firefox 中,顺序是:
DOMContentLoaded
window.onload
$(window).on('load', function() { ... });
$(document).ready();
$(function() { ... });
window.onload 和 jQuery window onLoad 都在 jQuery 文档就绪事件之前触发。我很确定这一定是 jQuery 或 Firefox 中的某种错误。谁可以给我解释一下这个?谢谢你。
铬版本:81.0.4044.138
火狐版本:75.0
在 macOS 和 Linux 中都进行了尝试,结果相同。
解决方案
这似乎是一个 jQuery 问题。我这样测试过:
当我使用 vanilla JS 函数时,我在 firefox 中得到了正确的顺序(首先触发 DOM Ready 然后窗口加载):
document.addEventListener('DOMContentLoaded', function(event) { console.log('DOMContentLoaded'); }); window.addEventListener('load', function(event) { console.log('window load'); });
当我使用 jQuery 时,我得到了错误的顺序(首先触发窗口加载,然后是 DOM 就绪):
$( window ).on( 'load', function() { console.log('window load'); }); $(function () { console.log('DOM Ready'); });
注意:这种错误的顺序只有在资源被缓存并且 Web 控制台关闭时才会发生。
同样的方式,您可以通过运行以下代码来验证触发事件的正确顺序:
document.addEventListener('readystatechange', function(event) {
console.log( 'readystatechange', document.readyState );
});
在 firefox 中,它总是首先触发“交互式”状态(例如 DOMContentLoaded),然后是“完成”状态(例如窗口加载)。
因此,不是 DOMContentLoaded 事件在窗口加载事件之前触发,而是 jQuery 的 DOM 就绪事件处理程序由于某种原因在窗口加载事件之前触发。
这是在最新的 jQuery 版本 3.5.1 上测试的。在 Mac 上运行的 Firefox 版本 82.0.3(64 位)。
现在,我通过添加一个标志变量并在 jQuery 的 DomReady 事件中检查它来使用一个简单的解决方法。如果在触发 jQuery 的 DOM Ready 事件时已经加载了窗口,我将运行必须在窗口加载时再次运行的函数。它并不理想或优雅,但完全满足简单的网页脚本。
var windowLoaded = false;
$( window ).on( 'load', function() {
windowLoaded = true;
runMyWindowLoadFunctions();
} );
$(function() {
if ( windowLoaded ) {
// Beware, runMyWindowLoadFunctions will run twice
runMyWindowLoadFunctions();
}
});
更新
刚刚检查了就绪事件的 jQuery 源代码https://github.com/jquery/jquery/blob/master/src/core/ready.js
// The ready event handler and self cleanup method
function completed() {
document.removeEventListener( "DOMContentLoaded", completed );
window.removeEventListener( "load", completed );
jQuery.ready();
}
// Catch cases where $(document).ready() is called
// after the browser event has already occurred.
if ( document.readyState !== "loading" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
window.setTimeout( jQuery.ready );
} else {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", completed );
// A fallback to window.onload, that will always work
window.addEventListener( "load", completed );
}
如您所见,可能会在处理 jQuery 脚本之前触发窗口加载事件,在这种情况下,jQuery 正在运行“就绪”事件处理程序。据我了解,jQuery 不会在运行窗口加载事件处理程序之前检查其“就绪”事件处理程序是否已被触发。
推荐阅读
- variables - _ 在变量名谷歌应用程序脚本中?
- angular - Docker 容器启动 monorepo 应用程序很慢
- stm32 - STM32 BluePill LED 闪光灯使用 HAL_GPIO_TogglePin 表现异常
- python - PySpark Sql 列名中包含破折号/连字符
- android - 画布绘制位图在 Android 10 上崩溃,但在 Android 8 上没有
- python-3.x - 如何使用熊猫在数据框中添加一个空列(不指定列名)?
- c++ - 如果评估,为什么 constexpr 中的代码无法访问?
- python - python中的分支故事。- 我的代码有什么问题?
- vue.js - defaultProtocol 不适用于带有 ckeditor5-vue 的链接
- python - 正则表达式:将“空白”字符和 - 字符更改为 null