html中重排和重繪問題

HTML頁面進行重繪和重排(迴流)

1 核心問題講解

瀏覽器的運行機制:
  1. 構建DOM樹(parse):渲染引擎解析HTML文檔,首先將標籤轉換成DOM樹中的DOM node(包括js生成的標籤)生成內容樹(Content Tree/DOM Tree);
  2. 構建渲染樹(construct):解析對應的CSS樣式文件信息(包括js生成的樣式和外部css文件),而這些文件信息以及HTML中可見的指令(如,構建渲染樹(Rendering Tree/Frame Tree);render tree中每個NODE都有自己的style,而且render tree不包含隱藏的節點(比如display:none的節點,還有head節點),因爲這些節點不會用於呈現
  3. 佈局渲染樹(reflow/layout):從根節點遞歸調用,計算每一個元素的大小、位置等,給出每個節點所應該在屏幕上出現的精確座標;
  4. 繪製渲染樹(paint/repaint):遍歷渲染樹,使用UI 層來繪製每個節點。

重繪(repaint或redraw)

​ 當盒子的位置、大小以及其他屬性,例如顏色、字體大小等都確定下來之後,瀏覽器便把這些原色都按照各自的特性繪製一遍,將內容呈現在頁面上。

重繪是指一個元素外觀的改變所觸發的瀏覽器行爲,瀏覽器會根據元素的新屬性重新繪製,使元素呈現新的外觀。

觸發重繪的條件:改變元素外觀屬性。如:color,background-color等。****

**注意:**table及其內部元素可能需要多次計算才能確定好其在渲染樹中節點的屬性值,比同等元素要多花兩倍時間,這就是我們儘量避免使用table佈局頁面的原因之一。

重排(重構/迴流/reflow):當渲染樹中的一部分(或全部)因爲元素的規模尺寸,佈局,隱藏等改變而需要重新構建, 這就稱爲迴流(reflow)。每個頁面至少需要一次迴流,就是在頁面第一次加載的時候。

重繪和重排的關係:在迴流的時候,瀏覽器會使渲染樹中受到影響的部分失效,並重新構造這部分渲染樹,完成迴流後,瀏覽器會重新繪製受影響的部分到屏幕中,該過程稱爲重繪。

所以,重排必定會引發重繪,但重繪不一定會引發重排。

觸發重排的條件:任何頁面佈局和幾何屬性的改變都會觸發重排,比如:

1、頁面渲染初始化;(無法避免)

2、添加或刪除可見的DOM元素;

3、元素位置的改變,或者使用動畫;

4、元素尺寸的改變——大小,外邊距,邊框;

5、瀏覽器窗口尺寸的變化(resize事件發生時);

6、填充內容的改變,比如文本的改變或圖片大小改變而引起的計算值寬度和高度的改變;

7、讀取某些元素屬性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) )

重繪重排的代價:耗時,導致瀏覽器卡慢。****

2.問題擴展

優化:

1、瀏覽器自己的優化:瀏覽器會維護1個隊列,把所有會引起迴流、重繪的操作放入這個隊列,等隊列中的操作到了一定的數量或者到了一定的時間間隔,瀏覽器就會flush隊列,進行一個批處理。這樣就會讓多次的迴流、重繪變成一次迴流重繪。

2、我們要注意的優化:我們要減少重繪和重排就是要減少對渲染樹的操作,則我們可以合併多次的DOM和樣式的修改。並減少對style樣式的請求。

(1)直接改變元素的className

(2)display:none;先設置元素爲display:none;然後進行頁面佈局等操作;設置完成後將元素設置爲display:block;這樣的話就只引發兩次重繪和重排;

(3)使用cloneNode(true or false) 和 replaceChild 技術,引發一次迴流和重繪;

(4)將需要多次重排的元素,position屬性設爲absolute或fixed,元素脫離了文檔流,它的變化不會影響到其他元素;

(5)如果需要創建多個DOM節點,可以使用DocumentFragment創建完後一次性的加入document;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章