重排(重構/回流/reflow):當渲染樹中的一部分(或全部)因為元素的規模尺寸,布局,隱藏顯示等改變而需要重新構建, 這就稱為回流(reflow)。每個頁面至少需要一次回流,就是在頁面第一次載入的時候。
重繪(repaint):當盒子的位置、大小以及其他屬性,例如顏色、字型大小等都確定下來之後,瀏覽器便把這些元素都按照各自的屬性繪製一遍,將內容呈現在頁面上。重繪是指乙個元素外觀的改變(如顏色、背景色等)所觸發的瀏覽器行為,瀏覽器會根據元素的新屬性重新繪製,使元素呈現新的外觀。
重繪和重排的關係:在回流的時候,瀏覽器會使渲染樹中受到影響的部分失效,並重新構造這部分渲染樹,完成回流後,瀏覽器會重新繪製受影響的部分到螢幕中,該過程稱為重繪。所以,重排必定會引發重繪,但重繪不一定會引發重排。
重排觸發條件:任何頁面布局和幾何屬性的改變都會觸發重排,比如:
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) )
觸發重繪的條件:改變元素外觀屬性。如:color,background-color等。
注意:table及其內部元素可能需要多次計算才能確定好其在渲染樹中節點的屬性值,比同等元素要多花兩倍時間,這就是我們盡量避免使用table布局頁面的原因之一。
如果進行大量的重排重繪操作,會導致瀏覽器很慢,十分卡頓,十分影響使用者體驗。那麼我們該如何優化呢?
首先,瀏覽器在渲染的時候就已經做了渲染優化處理:瀏覽器會維護1個佇列,把所有會引起回流、重繪的操作放入這個佇列,等佇列中的操作到了一定的數量或者到了一定的時間間隔,瀏覽器就會flush佇列,進行乙個批處理。這樣就會讓多次的回流、重繪變成一次回流重繪。
其次,是我們程式自身的優化,需要減少對rednder tree的操作,可以從以下幾個方面著手:
(1)直接改變元素的classname,而不是使用js來依次改變元素的屬性,那樣會造成多次重繪;
(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();for(let i=0;i<10;i++)
重排 reflow 和重繪 repaint
什麼是重排 引起dom樹重新計算的行為。什麼時候會發生重排 新增或刪除可見的dom元素 元素的位置改變 元素的尺寸大小改變 元素的內容改變 頁面渲染初始化 瀏覽器視窗尺寸改變 什麼是重繪 元素可見的外觀被改變,但並沒有影響到布局 什麼時候會發生重繪 dom元素的字型顏色 改變visibility o...
網頁的重排 reflow 與重繪 repaint
當頁面布局和幾何屬性改變時就會發生 重排 下述情況中會傳送重排 由於每次重排都會產生計算消耗,大多數瀏覽器通過佇列化修改並批量執行來優化重排過程。獲取布局資訊的操作會導致佇列重新整理 offsettop offsetleft offsetwidth offsetheight scrolltop sc...
回流 reflow 重繪 repaint
首先我們要明白的是,頁面的顯示過程分為以下幾個階段 生成dom樹 包括display none的節點 在dom樹的基礎上根據節點的集合屬性 margin,padding,width,height等 生成render樹 不包括display none,head節點,但是包括visibility hid...