頁面生命週期內,有兩個很是重要的事件: 1.DOMContentLoaded 此時瀏覽器已經徹底加載了HTML文件,而且DOM樹已經生成好了。可是其餘外部資源,如樣式文件、圖片、字體等並無加載好 2.Load 此時瀏覽器已經將全部的資源都加載完畢,能夠正確讀取頁面中的資源。javascript
兩個事件標識了兩種不一樣的時刻: 1.DOMContentLoaded DOM已經完成加載,此時能夠爲這些DOM元素綁定事件,初始化接口等 2.Load 其餘外部資源均已加載完成,能夠正確讀出這些資源的信息,如圖片的寬高等css
使用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
當解析器(HTML Paser)讀取到<script>...</script>
內聯標籤時,會阻塞DOM構建,它會當即執行腳本,緣由是可能這些腳本會影響DOM,所以須要等到這些腳本都執行完成了,纔會觸發DOMContentLoaded
事件。 外部腳本(<script src="...">...</script>
)也是如此,瀏覽器須要等到加載後再執行完成才能夠繼續執行。dom
是否可讓外部引用的腳本延後執行,答案是能夠的。async
和defer
屬性可讓外部腳本延後執行,而不阻塞瀏覽器解析文檔。async
和defer
僅在<script src="...">...</script>
情形下起做用,對內聯腳本是無效的。用戶能夠在腳本完成加載前,就能夠看到頁面了,提高了用戶體驗。異步
async & defer
這兩個屬性都是告訴瀏覽器,標記的腳本不須要等待它加載完成,瀏覽器能夠繼續完成DOM構建和渲染 二者的區別以下:async
async | defer | |
---|---|---|
執行順序 | 誰先完成下載誰先執行 | 執行順序始終遵循加載的順序,即便先下載完成了 |
DOMContentLoaded | 若是頁面加載時間較長,腳本可能會先執行;絕大多數會在DOMContentLoaded以後執行,但必定是在Load事件以前執行 | 腳本會在DOMContentLoaded以前執行,但不阻塞瀏覽器加載和解析文檔,即defer腳本與瀏覽器加載順序無關前後 |
所以async
更符合一些應用場景。函數
對於外部樣式文件而言,並不會影響到DOMCotentLoaded事件,它並不會等待外部樣式文件加載完成。 可是!!!,若是DOMContentLoaded
所屬的script以前出現的link樣式,那麼DOMContentLoaded
等待樣式加載完成。以下:oop
<link type="text/css" rel="stylesheet" href="style.css"> <script> document.addEventListener("DOMContentLoaded", function(){ // ... }); </script> 複製代碼
緣由是瀏覽器猜想腳本可能會讀取一些樣式信息,如位置、顏色,顯然腳本就須要等到樣式的加載完成了。
這個是順便引出的話題,你知道瀏覽器內置的表單自動填充在何時完成麼?沒錯,就是DOMContentLoaded觸發的時候
當全部外部資源都完成加載後,瀏覽器觸發load事件,此時能夠讀取外部資源信息了
<script> window.onload = function() { alert('Page loaded'); // image is loaded at this time alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`); }; </script> 複製代碼
咱們一般能夠經過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源碼,頗有意思