DOMContentLoaded和load事件之间的区别是什么?


当前回答

下面是一些适用于我们的代码。我们发现MSIE在使用DomContentLoaded时会出现一些错误,当没有额外的资源被缓存时似乎会有一些延迟(根据我们的控制台日志,最高可达300ms),并且当它们被缓存时触发得太快了。所以我们采取了MISE的退路。不管DomContentLoaded是在外部JS文件之前还是之后触发doStuff()函数。

// detect MSIE 9,10,11, but not Edge
ua=navigator.userAgent.toLowerCase();isIE=/msie/.test(ua);

function doStuff(){
    //
}
if(isIE){
    // play it safe, very few users, exec ur JS when all resources are loaded
    window.onload=function(){doStuff();}
} else {
    // add event listener to trigger your function when DOMContentLoaded
    if(document.readyState==='loading'){
        document.addEventListener('DOMContentLoaded',doStuff);
    } else {
        // DOMContentLoaded already loaded, so better trigger your function
        doStuff();
    }
}

其他回答

下面是一些适用于我们的代码。我们发现MSIE在使用DomContentLoaded时会出现一些错误,当没有额外的资源被缓存时似乎会有一些延迟(根据我们的控制台日志,最高可达300ms),并且当它们被缓存时触发得太快了。所以我们采取了MISE的退路。不管DomContentLoaded是在外部JS文件之前还是之后触发doStuff()函数。

// detect MSIE 9,10,11, but not Edge
ua=navigator.userAgent.toLowerCase();isIE=/msie/.test(ua);

function doStuff(){
    //
}
if(isIE){
    // play it safe, very few users, exec ur JS when all resources are loaded
    window.onload=function(){doStuff();}
} else {
    // add event listener to trigger your function when DOMContentLoaded
    if(document.readyState==='loading'){
        document.addEventListener('DOMContentLoaded',doStuff);
    } else {
        // DOMContentLoaded already loaded, so better trigger your function
        doStuff();
    }
}

domContentLoaded: marks the point when both the DOM is ready and there are no stylesheets that are blocking JavaScript execution - meaning we can now (potentially) construct the render tree. Many JavaScript frameworks wait for this event before they start executing their own logic. For this reason the browser captures the EventStart and EventEnd timestamps to allow us to track how long this execution took. loadEvent: as a final step in every page load the browser fires an “onload” event which can trigger additional application logic.

来自Mozilla开发者中心:

DOMContentLoaded事件在文档被删除时被触发 完全加载和解析,无需等待样式表,图像, 和子帧完成加载(load事件可以用来检测 一个完整的页面)。

DOMContentLoaded事件将在DOM层次结构完全构建完成后立即触发,load事件将在所有图像和子帧完成加载时触发。

DOMContentLoaded可以在大多数现代浏览器上运行,但不能在IE上运行,包括IE9及以上版本。在旧版本的IE上有一些变通方法来模拟这个事件,比如jQuery库上使用的,它们附加了IE特定的onreadystatechange事件。

为了充分理解,我建议阅读以下文章:

什么是DOM和CSSOM: https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model 渲染树是什么:https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction 所有与DOMContentLoaded、load和第一次打印相关的内容是怎样的: https://developers.google.com/web/fundamentals/performance/critical-rendering-path/analyzing-crp

简而言之:

DOMContentLoaded事件是在创建DOM时触发的(更多DOM是什么,请参阅链接1),load事件是在加载DOM、CSSOM和所有其他资源时触发的。如果你没有Javascript,那么你的网页加载的顺序可能是这样的:

或者用检查窗口的话来说,DOMContentLoaded事件将比load事件更早被触发(蓝线表示DOMContentLoaded,红线表示load事件):

然而,如果你使用Javascript(不是异步或延迟),那么DOM创建将等待JS加载。因为JS也会修改CSS,所以JS会等待CSSOM加载。

由于这是最常见的情况,因此在大多数场景中,DOMContentLoaded事件的创建实际上必须等待样式表也被加载。

加载链看起来像这样:

因此,DOMContentLoaded和load之间的主要区别是,在这种情况下,只有图像的加载时间,它可以与样式表和JS并行下载。

注意,如果你在JS中使用async或defer,就不会发生这种情况: