瀏覽器運行機制圖:css
瀏覽器的運行機制:layout:佈局;node
一、構建DOM樹(parse):渲染引擎解析HTML文檔,首先將標籤轉換成DOM樹中的DOM node(包括js生成的標籤)生成內容樹(Content Tree/DOM Tree);後端
二、構建渲染樹(construct):解析對應的CSS樣式文件信息(包括js生成的樣式和外部css文件),而這些文件信息以及HTML中可見的指令(如<b></b>),構建渲染樹(Rendering Tree/Frame Tree);瀏覽器
三、佈局渲染樹(reflow/layout):從根節點遞歸調用,計算每個元素的大小、位置等,給出每一個節點所應該在屏幕上出現的精確座標;緩存
四、繪製渲染樹(paint/repaint):遍歷渲染樹,使用UI後端層來繪製每一個節點。app
重繪(repaint或redraw):當盒子的位置、大小以及其餘屬性,例如顏色、字體大小等都肯定下來以後,瀏覽器便把這些原色都按照各自的特性繪製一遍,將內容呈如今頁面上。佈局
重繪是指一個元素外觀的改變所觸發的瀏覽器行爲,瀏覽器會根據元素的新屬性從新繪製,使元素呈現新的外觀。字體
觸發重繪的條件:改變元素外觀屬性。如:color,background-color等。優化
注意:table及其內部元素可能須要屢次計算才能肯定好其在渲染樹中節點的屬性值,比同等元素要多花兩倍時間,這就是咱們儘可能避免使用table佈局頁面的緣由之一。動畫
重排(重構/迴流/reflow):當渲染樹中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建, 這就稱爲迴流(reflow)。每一個頁面至少須要一次迴流,就是在頁面第一次加載的時候。
重繪和重排的關係:在迴流的時候,瀏覽器會使渲染樹中受到影響的部分失效,並從新構造這部分渲染樹,完成迴流後,瀏覽器會從新繪製受影響的部分到屏幕中,該過程稱爲重繪。
因此,重排一定會引起重繪,但重繪不必定會引起重排。
觸發重排的條件:任何頁面佈局和幾何屬性的改變都會觸發重排,好比:
一、頁面渲染初始化;(沒法避免)
二、添加或刪除可見的DOM元素;
三、元素位置的改變,或者使用動畫;
四、元素尺寸的改變——大小,外邊距,邊框;
五、瀏覽器窗口尺寸的變化(resize事件發生時);
六、填充內容的改變,好比文本的改變或圖片大小改變而引發的計算值寬度和高度的改變;
七、讀取某些元素屬性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) )
重繪重排的代價:耗時,致使瀏覽器卡慢。
優化:
一、瀏覽器本身的優化:瀏覽器會維護1個隊列,把全部會引發迴流、重繪的操做放入這個隊列,等隊列中的操做到了必定的數量或者到了必定的時間間隔,瀏覽器就會flush隊列,進行一個批處理。這樣就會讓屢次的迴流、重繪變成一次迴流重繪。
二、咱們要注意的優化:咱們要減小重繪和重排就是要減小對渲染樹的操做,則咱們能夠合併屢次的DOM和樣式的修改。並減小對style樣式的請求。
(1)直接改變元素的className
(2)display:none;先設置元素爲display:none;而後進行頁面佈局等操做;設置完成後將元素設置爲display:block;這樣的話就只引起兩次重繪和重排;
(3)不要常常訪問瀏覽器的flush隊列屬性;若是必定要訪問,能夠利用緩存。將訪問的值存儲起來,接下來使用就不會再引起迴流;
(4)使用cloneNode(true or false) 和 replaceChild 技術,引起一次迴流和重繪;
(5)將須要屢次重排的元素,position屬性設爲absolute或fixed,元素脫離了文檔流,它的變化不會影響到其餘元素;
(6)若是須要建立多個DOM節點,可使用DocumentFragment建立完後一次性的加入document;
var fragment = document.createDocumentFragment(); var li = document.createElement('li'); li.innerHTML = 'apple'; fragment.appendChild(li); var li = document.createElement('li'); li.innerHTML = 'watermelon'; fragment.appendChild(li); document.getElementById('fruit').appendChild(fragment);
(7)儘可能不要使用table佈局。