window.onload 事件何时触发?

33

我对 window.onload 事件的触发时机有点困惑。例如:我有一个页面,其中有许多外部 JavaScript 文件,甚至还有按需加载脚本(动态创建标记)。所有这些代码都在页面中(即它不会在单击或其他操作时触发,应在加载时执行)。现在假设我在最后一个按需 JavaScript 中设置了 window.onload = somefunction()。是否可能在所有脚本实际加载完成之前就触发 window.onload?

2个回答

30

window.onload(也称为body.onload)在主HTML、所有CSS、所有图像和所有其他资源加载和渲染后被触发。因此,如果你的图像停滞不前,这可能需要一些时间。

如果您只需要HTML(DOM),则可以使用jQuery的$(document).ready() - 它会在解析HTML之后但在浏览器完成加载所有外部资源(图像和在HTML中在您的脚本元素之后的样式表)之前触发。

页面中嵌入的脚本会在浏览器解析每个</script>时执行。因此,要在任何其他脚本之前执行脚本,请在<head>后的第一个位置添加<script>标记。

这意味着您可以通过将<script>标记作为<body>的最后一个元素来“模拟”window.onload


5
@Paul是正确的。window.onload不会在浏览器解析</html>时触发,它会在所有图像、对象和其他资源都被下载和呈现后触发。你可能将其与变异事件DOMReady混淆了,后者在文档被解析后触发。此外,动态添加的脚本元素会异步下载,因此它们不受此规则的限制。 - Andy E
1
er, DOMContentLoaded,不是 DOMReady :) - Andy E
@Aaron:我只能指向MDC window.onload文档,因为据我所知,该事件并没有在任何规范中定义。你也可以运行我在答案中提供的示例页面,它显示了在动态添加的脚本被解析之前,onload事件已经触发。 - Andy E
1
body.onloadwindow.onload 是相同的 - body.onload 作为一种方式提供,可以通过 HTML <BODY> 元素直接设置 window.onload 处理程序,使用 onload 属性。只有当所有图像都被下载和渲染后,onload 才会触发。我相当确定这也适用于 CSS 图像。 - Andy E
1
window.onload和jQuery的$(document.ready())并不是响应中所暗示的相同的东西...前者在所有内容(图片和DOM)加载完毕后触发,而后者则在DOM准备就绪时触发。 - armyofda12mnkeys
显示剩余6条评论

6

不是的。 window.onload() 会在所有资源(文档、对象、图像、css等)完成渲染时被调用。

误读了问题。是的,完全有可能在动态添加的脚本下载完成之前就触发了 window.onload 事件。使用DOM(document.createElement())添加的脚本异步下载,并且不受通常规则的限制,即 window.onload() 等待所有资源先完成下载。

我为您设置了一个测试套件,http://jsfiddle.net/ywSMW/。此脚本会动态将jQuery脚本添加到DOM中,并在 onload 处理程序期间将 $ 的值写入控制台。然后再过一秒钟将该值再次写入。即使脚本被缓存,第一次写入控制台返回 undefined,这意味着在 jQuery 脚本被下载和解析之前,onload 事件已经被触发。

在IE和Chrome中进行了测试。


关于评论,如果要检查 onload 事件是否已经触发,可以在 onload 处理程序内设置全局变量的值:

var windowHasLoaded = false;

window.onload = function () {
    windowHasLoaded = true;
}

function doSomethingWhenWindowHasLoaded() {
    if (!windowHasLoaded) {
        // onload event hasn't fired yet, wait 100ms and check again 
        window.setTimeout(doSomethingWhenWindowHasLoaded, 100);
    } else {
        // onload event has already fired, so we can continue
    }        
}        

有没有办法在脚本中测试窗口是否已经加载? - Marius S.
1
@Marius S:是的,你可以检查document.readyState属性。当文档解析完成时,它的值为“loaded”。在触发onload之后,它的值为“complete”。 - Andy E
但是并非所有浏览器都支持readyState,这就是我提出问题的原因。 - Marius S.
@Marius:你在谈论哪些浏览器?document.readyState 在IE、Firefox、Chrome、Safari和Opera中都得到支持。 - Andy E
@AndyEarnshaw,我们能否强制文档等待动态脚本完成加载,然后完成其过程?比如说,我正在动态加载AngularJS,如果我按照正常方式加载,ng-app将会崩溃,因为Angular尚未完成加载!onload和DOMContentLoaded不会等待动态脚本!有什么替代方案吗? - Amgad Fahmi
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接