瀏覽器渲染頁面常見問題

構建過程當中可能會產生的阻塞

  • html的代碼,是從上到下一行行執行的,也就是說若是js代碼寫在head頭裏,且沒有用加在window.onload方法裏,那麼他是沒法讀取到body裏的標籤的。之因此加在window.onload裏能夠執行,是由於,window.onload裏的函數會在dom樹加載以後執行。
  • 在遇到link標籤後,會在link加載(從服務器下載)完畢後,再執行後續代碼。但與此同時,若是還有外部文件,則是同時加載(不阻塞後續外部文件linkscript加載)。可是外部文件內的代碼不會執行,只會在代碼解析到它的時候執行。
  • script標籤會阻塞html解析,由於js可能會改變domcss,所以瀏覽器會先解析script,避免浪費時間。 要想避免阻塞的話,可以使用deferasync
  • 對於動態建立的link標籤不會阻塞其後動態建立的script的加載與執行,無論script標籤是否具備async屬性。
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>JS Bin</title>
        <script>
            var start = +new Date
        </script>
    
    </head>
    
    <body>
        test
        <script>
            var link = document.createElement('link')
            link.href = 'http://udacity-crp.herokuapp.com/style.css?rtt=2'
            link.rel = 'stylesheet'
            document.head.appendChild(link)
        
            var script = document.createElement('script')
            script.src = 'http://udacity-crp.herokuapp.com/time.js?rtt=1&a'
            document.head.appendChild(script)
        </script>
        <div id="result"></div>
        <script>
            var end = +new Date
            document.getElementById('result').innerHTML = end - start
        </script>
    </body>
    </html>
    複製代碼
  • js添加async屬性以後,script加載的外部文件成爲了異步加載,這時至關於它於本來的html解析過程同步進行。因此他不會被任何加載過程阻塞,只會在本身加載完成以後執行。可是,異步執行的影響就是,它如要讀取dom節點,極可能會失敗,由於它的加載和html解析過程沒有了前後順序。另外,若是它要輸出動態的dom節點,就沒法保證節點的位置,由於它添加的節點,是在html已解析的節點下順序添加的。

    <script src="http://localhost:8080/test.js" async></script>
    複製代碼

  • js添加 defer屬性以後, script加載的外部文件成爲了異步加載,執行是同步的。腳本加載不阻塞頁面的解析,腳本在獲取完後並不當即執行,而是等到 DOM樹加載完畢執行。
    以下代碼,加上 defer後會報錯 Uncaught ReferenceError: $ is not definedDOM樹渲染結束前 body裏的 script已經執行了

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>JS Bin</title>
        <script defer src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    </head>
    
    <body>
        <div id="d1">我是內容</div>
        <script >
            console.log($('#d1').html())
        </script>
    </body>
    </html>
    複製代碼

什麼狀況會引發重排/迴流(reflow)

  • 添加或者刪除可見的DOM元素;
  • 元素位置改變——display、float、position、overflow等等;
  • 元素尺寸改變——邊距、填充、邊框、寬度和高度
  • 內容改變——好比文本改變或者圖片大小改變而引發的計算值寬度和高度改變;
  • 頁面渲染初始化;
  • 瀏覽器窗口尺寸改變——resize事件發生時;

如何減小和避免重排

  • Reflow 的成本比 Repaint 的成本高得多的多。一個節點的 Reflow 頗有可能致使子節點,甚至父節點以及兄弟節點的 Reflow
  • 直接改變className,若是動態改變樣式,則使用cssText(考慮沒有優化的瀏覽器)
  • 讓要操做的元素進行」離線處理」,處理完後一塊兒更新;
    1. 使用DocumentFragment進行緩存操做,引起一次迴流和重繪;
    2. 使用display:none技術,只引起兩次迴流和重繪;
    3. 使用cloneNode(true or false)replaceChild技術,引起一次迴流和重繪;
  • 不要常常訪問會引發瀏覽器flush隊列的屬性,若是你確實要訪問,利用緩存;
  • 讓元素脫離動畫流,減小回流的Render Tree的規模;

DOM是什麼?

DOM(Document Object Model——文檔對象模型)是用來呈現以及與任意 HTML 或 XML文檔交互的API。DOM 是載入到瀏覽器中的文檔模型,以節點樹的形式來表現文檔,每一個節點表明文檔的構成部分(例如:頁面元素、字符串或註釋等等)。css

DOM的做用

  • DOM 將HTML文檔呈現爲帶有元素、屬性和文本的樹結構(節點樹)。
  • 它容許運行在瀏覽器中的代碼訪問文件中的節點並與之交互。節點能夠被建立,移動或修改。事件監聽器能夠被添加到節點上並在給定事件發生時觸發。

什麼是DOM渲染?

DOM渲染指的是對於瀏覽器中展示給用戶的DOM文檔的生成的過程。html

DOM樹的構建是文檔加載完成開始的?

構建DOM樹是一個漸進過程,爲達到更好用戶體驗,渲染引擎會盡快將內容顯示在屏幕上。它沒必要等到整個HTML文檔解析完畢以後纔開始構建render數和佈局。jquery

Render樹是DOM樹和CSSOM樹構建完畢纔開始構建的嗎?

這三個過程在實際進行的時候不是徹底獨立,而是會有交叉。會形成一邊加載,一遍解析,一遍渲染的工做現象。瀏覽器

相關文章
相關標籤/搜索