Html 的生命周期


零、序言

  vue 用多了,自然離不開生命周期。最近突發奇想,加上之前看過的文章中關於 script 標簽中的 async 和 defer 的搗糨糊,決定整理一下,攻克這個模糊點。

  當然,最多的還是與 script 標簽相關的前兩個周期,后倆個周期並沒有過多的復雜點,因此會着重描述前兩個。

 

  參考文章:

    1.頁面生命周期

    2.HTML,javascript,image等加載,DOM解析,js執行生命周期

 

一、頁面周期

  1.DOMContentLoaded - 瀏覽器已經加載了 Html, DOM 樹已經構建完畢,但是 img 和外部樣式表等資源可能還沒有下載完畢。

  2.load - 瀏覽器已經完全加載了所有資源。

  3.beforeunload - 用戶即將離開頁面。

  4.unload - 用戶離開頁面。

 

  每一個事件都有特定的用途,前兩個如其名,beforeunload 會給用戶彈出個確認框,unload 則不會。

 

二、DOMContentLoaded

  DOMContentLoaded 事件由 document 對象觸發,我們可以使用 addEventListener 來觸發。

  正如前文所說,在這個事件觸發的時候,我們如果獲取某些 img 的寬度和高度的話,得到的可能是0。

  當然這里是有陷阱的。

 

  1. 與腳本(<script />)

    首先有一點,瀏覽器的 UI 渲染線程和 JS 引擎是互斥的,當 JS 引擎執行時 UI 線程會被掛起。因此,當瀏覽器在解析 HTML 時遇到 <script /> 時,將不會繼續構建 DOM 樹,轉而取解析、執行腳本,所以 DOMContentLoaded 有可能在所有腳本執行完畢之后觸發。

    外部腳本(通過 src  引入)的加載和解析和自帶的一樣會暫停 DOM 樹的構建,這里  DOMContentLoaded 會等待。

    不過有兩個特殊的情況,如果外部腳本上帶有 async 或者 defer 屬性,那么瀏覽器會繼續執行 DOM 解析而不需要等待腳本的完全執行,所以這一直時外部腳本的優化方案之一。(async 和 defer 屬性僅對外部腳本起作用, 當 src 不存在的時候會被自動忽略)

    關於 async 和 defer 與 DOM 的解析順序如下圖所示:

 

    既然提到了 async 和 defer,  也順帶整理一下他們的異同:

  async defer
順序 帶有 async 的腳本是優先執行先加載完的腳本,即他們在頁面中的順序並不保證他們的執行順序。 帶有 defer 的腳本時按照他們在頁面中出現的順序依次執行。
DOMContentLoaded 帶有async的腳本也許會在頁面沒有完全下載完之前就加載,這種情況會在腳本很小或本緩存,並且頁面很大的情況下發生。 帶有defer的腳本會在頁面加載和解析完畢后執行,剛好在 DOMContentLoaded之前執行。

 

    所以 async 用在完全沒有依賴和被依賴的腳本上。

 

三、load

  load 事件是在 window 對象上的,這與 DOMContentLoaded 不同。該事件在所有文件包括樣式表,圖片和其他資源下載完畢后觸發。既然這樣規定,自然該干啥干啥,沒什么明顯的陷阱。

 

四、beforeunload

  如果用戶即將離開頁面或關閉窗口時,beforeunload 事件將會被觸發以進行額外的確認。舉個例子:

window.onbeforeunload = function() {
  return "There are unsaved changes. Leave now?";
};

  當然,如果在 chrome 和 firefox 瀏覽器中會忽略返回的自定義的字符串,這是出於安全考慮的。

 

五、unload

  unload 事件與 load 事件一樣,是在 window 對象上的,觸發時間為用戶關閉該頁面的時候,我們可以做一些不存在延時的任務,比如關閉彈層等等。

 

六、readyState

  document.readyState 這個只讀屬性可以告訴程序當前文檔加載到哪一個步驟,它有三個值:

    1. loading - 加載,document 仍在加載中;

    2. interactive - 互動,文檔已經完成加載,文檔已被解析,但是諸如圖像,樣式表和框架之類的子資源仍在加載。

    3. complete - 文檔和所有子資源已完成加載。狀態表示 load 事件即將被觸發。

  而這個屬性的每次改變同樣有一個事件可以監聽:

document.addEventListener('readystatechange', () => console.log(document.readyState));

   不過這個 change 事件很少會被用到,可能出現的地方在某些第三方類庫中判斷一些依賴關系等地方。不詳述,具體可移步文首的文章或者 MDN。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM