【轉載】DOMContentLoaded與load的區別 DOMContentLoaded與load的區別

DOMContentLoaded與load的區別

 

(1)在chrome瀏覽器的開發過程當中,咱們會看到network面板中有這兩個數值,分別對應網 絡請求上的標誌線,這兩個時間數值分別表明什麼?javascript

(2)咱們一再強調將css放在頭部,將js文件放在尾部,這樣有利於優化頁面的性能,爲何這種方式可以優化性能?css

(3)在用jquery的時候,咱們通常都會將函數調用寫在ready方法內,這是什麼原理?html

首先看一下java

DOMContentLoaded顧名思義,就是dom內容加載完畢。那什麼是dom內容加載完畢呢?咱們從打開一個網頁提及。當輸入一個URL,頁面的展現首先是空白的,而後過一會,頁面會展現出內容,可是頁面的有些資源好比說圖片資源還沒法看到,此時頁面是能夠正常的交互,過一段時間後,圖片才完成顯示在頁面。從頁面空白到展現出頁面內容,會觸發DOMContentLoaded事件。而這段時間就是HTML文檔被加載和解析完成。jquery

這時候問題又來了,什麼是HTML文檔被加載和解析完成。要解決這個問題,咱們就必須瞭解瀏覽器渲染原理。面試

當咱們在瀏覽器地址輸入URL時,瀏覽器會發送請求到服務器,服務器將請求的HTML文檔發送回瀏覽器,瀏覽器將文檔下載下來後,便開始從上到下解析,解析完成以後,會生成DOM。若是頁面中有css,會根據css的內容造成CSSOM,而後DOM和CSSOM會生成一個渲染樹,最後瀏覽器會根據渲染樹的內容計算出各個節點在頁面中的確切大小和位置,並將其繪製在瀏覽器上。chrome

 

 下面就是頁面加載和解析過程當中,瀏覽器的一個快照瀏覽器

 

上面咱們看到在解析html的過程當中,html的解析會被中斷,這是由於javascript會阻塞dom的解析。當解析過程當中遇到<script>標籤的時候,便會中止解析過程,轉而去處理腳本,若是腳本是內聯的,瀏覽器會先去執行這段內聯的腳本,若是是外鏈的,那麼先會去加載腳本,而後執行。在處理完腳本以後,瀏覽器便繼續解析HTML文檔。安全

同時javascript的執行會受到標籤前面樣式文件的影響。若是在標籤前面有樣式文件,須要樣式文件加載並解析完畢後才執行腳本。這是由於javascript能夠查詢對象的樣式。服務器

這裏須要注意一點,在如今瀏覽器中,爲了減緩渲染被阻塞的狀況,現代的瀏覽器都使用了猜想預加載。當解析被阻塞的時候,瀏覽器會有一個輕量級的HTML(或CSS)掃描器(scanner)繼續在文檔中掃描,查找那些未來可能可以用到的資源文件的url,在渲染器使用它們以前將其下載下來。

在這裏咱們能夠明確DOMContentLoaded所計算的時間,當文檔中沒有腳本時,瀏覽器解析完文檔便能觸發 DOMContentLoaded 事件;若是文檔中包含腳本,則腳本會阻塞文檔的解析,而腳本須要等位於腳本前面的css加載完才能執行。在任何狀況下,DOMContentLoaded 的觸發不須要等待圖片等其餘資源加載完成。

接下來,咱們來講說load,頁面上全部的資源(圖片,音頻,視頻等)被加載之後纔會觸發load事件,簡單來講,頁面的load事件會在DOMContentLoaded被觸發以後才觸發。

咱們在 jQuery 中常用的 $(document).ready(function() { // ...代碼... }); 其實監聽的就是 DOMContentLoaded 事件,而$(document).load(function() { // ...代碼... }); 監聽的是 load 事件。在用jquery的時候,咱們通常都會將函數調用寫在ready方法內,就是頁面被解析後,咱們就能夠訪問整個頁面的全部dom元素,能夠縮短頁面的可交互時間,提升整個頁面的體驗。

下面咱們在來看看如何實現這兩個函數

一、onload事件

   onload事件全部的瀏覽器都支持,因此咱們不須要什麼兼容,只要經過調用

window.onload = function(){
    
}

二、DOMContentLoaded 事件

DOMContentLoaded不一樣的瀏覽器對其支持不一樣,因此在實現的時候咱們須要作不一樣瀏覽器的兼容。

1)支持DOMContentLoaded事件的,就使用DOMContentLoaded事件;

2)IE六、IE7不支持DOMContentLoaded,但它支持onreadystatechange事件,該事件的目的是提供與文檔或元素的加載狀態有關的信息。

3)  更低的ie還有個特有的方法doScroll, 經過間隔調用:document.documentElement.doScroll("left");

  能夠檢測DOM是否加載完成。 當頁面未加載完成時,該方法會報錯,直到doScroll再也不報錯時,就表明DOM加載完成了。該方法更接近DOMContentLoaded的實現。

 

複製代碼
function ready(fn){

    if(document.addEventListener) {
        document.addEventListener('DOMContentLoaded', function() {
            document.removeEventListener('DOMContentLoaded',arguments.callee, false);
            fn();
        }, false);
    } 

    // 若是IE
    else if(document.attachEvent) {
        // 確保當頁面是在iframe中加載時,事件依舊會被安全觸發
        document.attachEvent('onreadystatechange', function() {
            if(document.readyState == 'complete') {
                document.detachEvent('onreadystatechange', arguments.callee);
                fn();
            }
        });

        // 若是是IE且頁面不在iframe中時,輪詢調用doScroll 方法檢測DOM是否加載完畢
        if(document.documentElement.doScroll && typeof window.frameElement === "undefined") {
            try{
                document.documentElement.doScroll('left');
            }
            catch(error){
                return setTimeout(arguments.callee, 20);
            };
            fn();
        }
    }
};
複製代碼

 

 最後咱們來回答這個問題:咱們爲何一再強調將css放在頭部,將js文件放在尾部

在面試的過程當中,常常會有人在回答頁面的優化中提到將js放到body標籤底部,緣由是由於瀏覽器生成Dom樹的時候是一行一行讀HTML代碼的,script標籤放在最後面就不會影響前面的頁面的渲染。那麼問題來了,既然Dom樹徹底生成好後頁面才能渲染出來,瀏覽器又必須讀徹底部HTML才能生成完整的Dom樹,script標籤不放在body底部是否是也同樣,由於dom樹的生成須要整個文檔解析完畢。

咱們再來看一下chrome在頁面渲染過程當中的,綠色標誌線是First Paint的時間。納尼,爲何會出現firstpaint,頁面的paint不是在渲染樹生成以後嗎?其實現代瀏覽器爲了更好的用戶體驗,渲染引擎將嘗試儘快在屏幕上顯示的內容。它不會等到全部HTML解析以前開始構建和佈局渲染樹。部分的內容將被解析並顯示。也就是說瀏覽器可以渲染不完整的dom樹和cssom,儘快的減小白屏的時間。假如咱們將js放在header,js將阻塞解析dom,dom的內容會影響到First Paint,致使First Paint延後。因此說咱們會將js放在後面,以減小First Paint的時間,可是不會減小DOMContentLoaded被觸發的時間。

相關文章
相關標籤/搜索