最近了解了下repaint和reflow的相關知識,覺得在頁面重構過程中就應該考慮前端開發(js)人員對dom進行操作,能夠減輕客戶浏覽器的鴨梨。
在這裡整理了一下相關資料,推薦看帖子底部的文章,如果覺得排版不夠好請移步我的博客圍觀。這是一個討論帖,拋磚引玉,大家說說自己工作中的經驗~
1. 什麼是 repaint 和 reflow?
一個頁面由兩部分組成:
DOM:描述該頁面的結構
render:描述 DOM 節點 (nodes) 在頁面上如何呈現
當 DOM 元素的屬性發生變化 (如 color) 時, 浏覽器會通知 render 重新描繪相應的元素, 此過程稱為 repaint。
如果該次變化涉及元素布局 (如 width), 浏覽器則拋棄原有屬性, 重新計算並把結果傳遞給 render 以重新描繪頁面元素, 此過程稱為 reflow。
這兩個過程是很耗費浏覽器性能的, 從 IE 系列和 Chrome 渲染頁面速度上的差距即可看出渲染引擎計算對應值和呈現並不一定高效, 而每次對元素的操作都會發生 repaints 或 reflow, 因此編寫 DOM 交互時如果不注意就會導致頁面性能低下.
頁面渲染的過程如下:
1.解析HTML代碼並生成一個 DOM 樹。
2.解析CSS文件,順序為:浏覽器默認樣式->自定義樣式->頁面內的樣式。
3.生成一個渲染樹(render tree)。這個渲染樹和DOM樹的不同之處在於,它是受樣式影響的。它不包括那些不可見的節點。
4.當渲染樹生成之後,浏覽器就會在屏幕上“畫”出所有渲染樹中的節點。
2. 什麼情況下會觸發浏覽器的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))
3. 怎麼優化?
1. 避免在document上直接進行頻繁的DOM操作,如果確實需要可以采用off-document的方式進行,具體的方法包括但不完全包括以下幾種:
引用:
1. 先將元素從document中刪除,完成修改後再把元素放回原來的位置
2. 將元素的display設置為”none”,完成修改後再把display修改為原來的值
3. 如果需要創建多個DOM節點,可以使用DocumentFragment創建完後一次性的加入document
2. 集中修改樣式
引用:
1. 盡可能少的修改元素style上的屬性
2. 盡量通過修改className來修改樣式
3. 通過cssText屬性來設置樣式值
3. 緩存Layout屬性值
引用:
對於Layout屬性中非引用類型的值(數字型),如果需要多次訪問則可以在一次訪問時先存儲到局部變量中,之後都使用局部變量,這樣可以避免每次讀取屬性時造成浏覽器的渲染。
4. 設置元素的position為absolute或fixed
引用:
在元素的position為static和relative時,元素處於DOM樹結構當中,當對元素的某個操作需要重新渲染時,浏覽器會渲染整個頁 面。將元素的position設置為absolute和fixed可以使元素從DOM樹結構中脫離出來獨立的存在,而浏覽器在需要渲染時只需要渲染該元素 以及位於該元素下方的元素,從而在某種程度上縮短浏覽器渲染時間,這在當今越來越多的Javascript動畫方面尤其值得考慮。
5. 權衡速度的平滑
引用:
比如實現一個動畫,以1個像素為單位移動這樣最平滑,但reflow就會過於頻繁,CPU很快就會被完全占用。如果以3個像素為單位移動就會好很多。
6. 不要用tables布局
引用:
不要用tables布局的另一個原因就是tables中某個元素一旦觸發reflow就會導致table裡所有的其它元素 reflow。在適合用table的場合,可以設置table-layout為auto或fixed,這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響范圍
7. 不要在css裡面寫expression
引用:
很多情況下都會觸發reflow,如果css裡有expression,每次都會重新計算一遍
參考文章:
1. 如何減少浏覽器repaint和reflow
2. Repaint, reflow/relayout, restyle
3. Reflows & Repaints: CSS Performance making your JavaScript slow?
4. Repaint 跟蹤浏覽器的渲染[如果你的FF是3.5beta+監聽網頁的重繪情況]