首先咱們要明白的是,頁面的顯示過程分爲如下幾個階段:css
一、生成DOM樹(包括display:none的節點)express
二、在DOM樹的基礎上根據節點的集合屬性(margin,padding,width,height等)生成render樹(不包括display:none,head節點,可是包括visibility:hidden的節點)瀏覽器
三、在render樹的基礎上繼續渲染顏色背景色等樣式緩存
Reflow:當render樹的一部分或者所有由於大小邊距等問題發生改變而須要重建的過程,叫作迴流。markdown
reflow會影響到dom的結構渲染,同時會觸發repaint,他會改變他自己與全部父輩元素(祖先),這種開銷是很是昂貴的,致使性能降低是必然的,頁面元素越多效果越明顯。app
Repaint(重繪):當諸如顏色背景等不會引發頁面佈局變化,而只須要從新渲染的過程叫作重繪。dom
repaint發生更改時,元素的外觀被改變,且在沒有改變佈局的狀況下發生,如改變outline,visibility,background color,不會影響到dom結構渲染。佈局
經過上述定義,能夠很明顯看出,重繪的代價要比迴流小,畢竟重繪只涉及樣式的改變,不涉及到佈局。性能
什麼狀況下會觸發瀏覽器的repaint/reflow?字體
1.DOM元素的添加、修改(內容)、刪除( Reflow + Repaint)
2.僅修改DOM元素的字體顏色(只有Repaint,由於不須要調整佈局)
3.應用新的樣式或者修改任何影響元素外觀的屬性
4.Resize瀏覽器窗口、滾動頁面
5.讀取元素的某些屬性(offsetLeft、offsetTop、offsetHeight、offsetWidth、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle(in IE))
6.改變字體大小
7.添加、刪除樣式表
8.內容的改變,如用戶在輸入框中寫字
9.激活僞類
10.設置style屬性
如何避免repaint/reflow?
1.先將元素從document中刪除,完成修改後再把元素放回原來的位置 2.將元素的display設置爲」none」,完成修改後再把display修改成原來的值* 3.若是須要建立多個DOM節點,可使用DocumentFragment建立完後一次性的加入document var fragment = document.createDocumentFragment(); fragment.appendChild(document.createTextNode(‘keenboy test 111’)); fragment.appendChild(document.createElement(‘br’)); fragment.appendChild(document.createTextNode(‘keenboy test 222’)); document.body.appendChild(fragment); 4.集中修改樣式** (1)儘量少的修改元素style上的屬性 (2)儘可能經過修改className來修改樣式 (3)經過cssText屬性來設置樣式值 element.style.width=」80px」; //reflow element.style.height=」90px」; //reflow element.style.border=」solid 1px red」; //reflow 以上就產生屢次reflow,調用的越多產生就越多 element.style.cssText=」width:80px;height:80px;border:solid 1px red;」; //reflow (4)緩存Layout屬性值 var left=elem.offsetLeft; 屢次使用left也就產生一次reflow (5)設置元素的position爲absolute或fixed 元素脫離標準流,也從DOM樹結構中脫離出來,在須要reflow時只須要reflow自身與下級元素 (6)避免使用expression,他會每次調用都會從新計算一遍(包括加載頁面) (7)儘可能不要用table佈局 table元素一旦觸發reflow就會致使table裏全部的其它元素 reflow。在適合用table的場合,能夠設置table-layout爲auto或fixed,這樣可讓table一行一行的渲染,這種作法也是爲了限制reflow的影響範圍