頁面生命週期——DOMContentLoaded&Loaded

頁面生命週期內,有兩個很是重要的事件: 1.DOMContentLoaded 此時瀏覽器已經徹底加載了HTML文件,而且DOM樹已經生成好了。可是其餘外部資源,如樣式文件、圖片、字體等並無加載好 2.Load 此時瀏覽器已經將全部的資源都加載完畢,能夠正確讀取頁面中的資源。javascript

兩個事件標識了兩種不一樣的時刻: 1.DOMContentLoaded DOM已經完成加載,此時能夠爲這些DOM元素綁定事件,初始化接口等 2.Load 其餘外部資源均已加載完成,能夠正確讀出這些資源的信息,如圖片的寬高等css

DOMContentLoaded

使用addEventListener監聽該事件:java

document.addEventListener('DOMContentLoaded', ready)
複製代碼

舉一個🌰瀏覽器

<script>
  function ready() {
    alert('DOM is ready');
    
    var img = document.getElementById('img')
    // 因爲圖片屬於外部資源,還沒有下載完成,所以暫沒法讀到數據,因此結果是0x0
    alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
  }

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

![](https://user-gold-cdn.xitu.io/2018/12/13/167a77b5d47a7ad1?w=177&h=160&f=gif&s=6854)
複製代碼

雖然DOMContentLoaded如咱們指望的那樣工做,但仍在個別狀況下有所不一樣markdown

異步scripts

當解析器(HTML Paser)讀取到<script>...</script>內聯標籤時,會阻塞DOM構建,它會當即執行腳本,緣由是可能這些腳本會影響DOM,所以須要等到這些腳本都執行完成了,纔會觸發DOMContentLoaded事件。 外部腳本(<script src="...">...</script>)也是如此,瀏覽器須要等到加載後再執行完成才能夠繼續執行。dom

是否可讓外部引用的腳本延後執行,答案是能夠的。asyncdefer屬性可讓外部腳本延後執行,而不阻塞瀏覽器解析文檔。asyncdefer僅在<script src="...">...</script>情形下起做用,對內聯腳本是無效的。用戶能夠在腳本完成加載前,就能夠看到頁面了,提高了用戶體驗。異步

async & defer

這兩個屬性都是告訴瀏覽器,標記的腳本不須要等待它加載完成,瀏覽器能夠繼續完成DOM構建和渲染 二者的區別以下:async

async defer
執行順序 誰先完成下載誰先執行 執行順序始終遵循加載的順序,即便先下載完成了
DOMContentLoaded 若是頁面加載時間較長,腳本可能會先執行;絕大多數會在DOMContentLoaded以後執行,但必定是在Load事件以前執行 腳本會在DOMContentLoaded以前執行,但不阻塞瀏覽器加載和解析文檔,即defer腳本與瀏覽器加載順序無關前後

所以async更符合一些應用場景。函數

Timeline

樣式阻塞

對於外部樣式文件而言,並不會影響到DOMCotentLoaded事件,它並不會等待外部樣式文件加載完成。 可是!!!,若是DOMContentLoaded所屬的script以前出現的link樣式,那麼DOMContentLoaded等待樣式加載完成。以下:oop

<link type="text/css" rel="stylesheet" href="style.css">
<script> document.addEventListener("DOMContentLoaded", function(){ // ... }); </script>
複製代碼

緣由是瀏覽器猜想腳本可能會讀取一些樣式信息,如位置、顏色,顯然腳本就須要等到樣式的加載完成了。

瀏覽器表單自動填充

這個是順便引出的話題,你知道瀏覽器內置的表單自動填充在何時完成麼?沒錯,就是DOMContentLoaded觸發的時候

window.onload

當全部外部資源都完成加載後,瀏覽器觸發load事件,此時能夠讀取外部資源信息了

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

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

複製代碼

Chrome DevTool中的load

image.png

咱們一般能夠經過DOMContentLoaded的時間去衡量一個頁面加載的速度,由於此時用戶已經能夠看到這個頁面,並能夠有一些交互了。

兼容性

以上提到的使用document.addEventListener監聽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 );
}
複製代碼

比較粗暴,反覆去嗅探是否能夠執行ready函數。有興趣去讀讀jQuery源碼,頗有意思

擴展閱讀

相關文章
相關標籤/搜索