頁(yè)面生命周期——DOMContentLoaded&Loaded

頁(yè)面生命周期內(nèi),有兩個(gè)非常重要的事件:
1.DOMContentLoaded
此時(shí)瀏覽器已經(jīng)完全加載了HTML文件,并且DOM樹已經(jīng)生成好了。但是其他外部資源,如樣式文件、圖片、字體等并沒(méi)有加載好
2.Load
此時(shí)瀏覽器已經(jīng)將所有的資源都加載完畢,可以正確讀取頁(yè)面中的資源。

兩個(gè)事件標(biāo)識(shí)了兩種不同的時(shí)刻:
1.DOMContentLoaded
DOM已經(jīng)完成加載,此時(shí)可以為這些DOM元素綁定事件,初始化接口等
2.Load
其他外部資源均已加載完成,可以正確讀出這些資源的信息,如圖片的寬高等

DOMContentLoaded

使用addEventListener監(jiān)聽(tīng)該事件:

document.addEventListener('DOMContentLoaded', ready)

舉一個(gè)??

<script>
  function ready() {
    alert('DOM is ready');
    
    var img = document.getElementById('img')
    // 由于圖片屬于外部資源,尚未下載完成,因此暫無(wú)法讀到數(shù)據(jù),所以結(jié)果是0x0
    alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
  }

  document.addEventListener("DOMContentLoaded", ready);
</script>

![](http://upload-images.jianshu.io/upload_images/280956-d030e8153b43d7be.gif?imageMogr2/auto-orient/strip)

雖然DOMContentLoaded如我們期望的那樣工作,但仍在個(gè)別情況下有所不同

異步scripts

當(dāng)解析器(HTML Paser)讀取到<script>...</script>內(nèi)聯(lián)標(biāo)簽時(shí),會(huì)阻塞DOM構(gòu)建,它會(huì)立即執(zhí)行腳本,原因是可能這些腳本會(huì)影響DOM,因此需要等到這些腳本都執(zhí)行完成了,才會(huì)觸發(fā)DOMContentLoaded事件。
外部腳本(<script src="...">...</script>)也是如此,瀏覽器需要等到加載后再執(zhí)行完成才可以繼續(xù)執(zhí)行。

是否可以讓外部引用的腳本延后執(zhí)行,答案是可以的。asyncdefer屬性可以讓外部腳本延后執(zhí)行,而不阻塞瀏覽器解析文檔。asyncdefer僅在<script src="...">...</script>情形下起作用,對(duì)內(nèi)聯(lián)腳本是無(wú)效的。用戶可以在腳本完成加載前,就可以看到頁(yè)面了,提升了用戶體驗(yàn)。

async & defer

這兩個(gè)屬性都是告訴瀏覽器,標(biāo)記的腳本不需要等待它加載完成,瀏覽器可以繼續(xù)完成DOM構(gòu)建和渲染
兩者的區(qū)別如下:

async defer
執(zhí)行順序 誰(shuí)先完成下載誰(shuí)先執(zhí)行 執(zhí)行順序始終遵循加載的順序,即使先下載完成了
DOMContentLoaded 如果頁(yè)面加載時(shí)間較長(zhǎng),腳本可能會(huì)先執(zhí)行;絕大多數(shù)會(huì)在DOMContentLoaded之后執(zhí)行,但一定是在Load事件之前執(zhí)行 腳本會(huì)在DOMContentLoaded之前執(zhí)行,但不阻塞瀏覽器加載和解析文檔,即defer腳本與瀏覽器加載順序無(wú)關(guān)先后

因此async更符合一些應(yīng)用場(chǎng)景。

Timeline

樣式阻塞

對(duì)于外部樣式文件而言,并不會(huì)影響到DOMCotentLoaded事件,它并不會(huì)等待外部樣式文件加載完成。
但是!?。?,如果一個(gè)腳本是緊跟著link樣式出現(xiàn),那么這個(gè)腳本就會(huì)等樣式加載完成了。如下:

<link type="text/css" rel="stylesheet" href="style.css">
<script>
  // the script doesn't not execute until the stylesheet is loaded
  alert(getComputedStyle(document.body).marginTop);
</script>

原因是瀏覽器猜測(cè)腳本可能會(huì)讀取一些樣式信息,如位置、顏色,顯然腳本就需要等到樣式的加載完成了。

這也是為什么我們最好把腳本文件放到HTML文檔的最后再加載,而不要把腳本放在head標(biāo)簽里,除非你清楚放在head標(biāo)簽里是必要的。

瀏覽器表單自動(dòng)填充

這個(gè)是順便引出的話題,你知道瀏覽器內(nèi)置的表單自動(dòng)填充在什么時(shí)候完成么?沒(méi)錯(cuò),就是DOMContentLoaded觸發(fā)的時(shí)候

window.onload

當(dāng)所有外部資源都完成加載后,瀏覽器觸發(fā)load事件,此時(shí)可以讀取外部資源信息了

<script>
  window.onload = function() {
    alert('Page loaded');

    // image is loaded at this time
    alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
  };
</script>

![](http://upload-images.jianshu.io/upload_images/280956-d030e8153b43d7be.gif?imageMogr2/auto-orient/strip)

Chrome DevTool中的load

image.png

我們通??梢酝ㄟ^(guò)DOMContentLoaded的時(shí)間去衡量一個(gè)頁(yè)面加載的速度,因?yàn)榇藭r(shí)用戶已經(jīng)可以看到這個(gè)頁(yè)面,并可以有一些交互了。

兼容性

以上提到的使用document.addEventListener監(jiān)聽(tīng)DOMCotentLoaded事件,在IE9+都是有效的。需要兼容IE低版本

// 摘抄自jQuery源碼
if ( document.readyState === "complete" ||
    ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
    // Handle it asynchronously to allow scripts the opportunity to delay ready
    window.setTimeout( jQuery.ready );
}

比較粗暴,反復(fù)去嗅探是否可以執(zhí)行ready函數(shù)。有興趣去讀讀jQuery源碼,很有意思

擴(kuò)展閱讀

DOMContentLoaded
onload
page lifecycle

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一:在制作一個(gè)Web應(yīng)用或Web站點(diǎn)的過(guò)程中,你是如何考慮他的UI、安全性、高性能、SEO、可維護(hù)性以及技術(shù)因素的...
    Arno_z閱讀 1,354評(píng)論 0 1
  • 1.幾種基本數(shù)據(jù)類型?復(fù)雜數(shù)據(jù)類型?值類型和引用數(shù)據(jù)類型?堆棧數(shù)據(jù)結(jié)構(gòu)? 基本數(shù)據(jù)類型:Undefined、Nul...
    極樂(lè)君閱讀 5,869評(píng)論 0 106
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,765評(píng)論 25 709
  • 還沒(méi)好好地感受盛夏,卻已入秋.廈門的秋沒(méi)有“滿地黃花堆積”.自然感受不到“這次第,怎一個(gè)愁字了得”.來(lái)廈快十...
    IVI_Y閱讀 355評(píng)論 3 1
  • 金思米/文 揭露微信投票中獎(jiǎng)之謎 一件事情,不同的眼睛,看法截然不同。同樣的事物,不同人的...
    金思米閱讀 1,180評(píng)論 5 4

友情鏈接更多精彩內(nèi)容