最近了解了下repaint和reflow的相關(guān)知識(shí),覺得在頁面重構(gòu)過程中就應(yīng)該考慮前端開發(fā)(js)人員對(duì)dom進(jìn)行操作,能夠減輕客戶瀏覽器的鴨梨。 在這里整理了一下相關(guān)資料,推薦看帖子底部的文章,如果覺得排版不夠好請(qǐng)移步我的博客圍觀。這是一個(gè)討論帖,拋磚引玉,大家說說自己工作中的經(jīng)驗(yàn)~
1. 什么是 repaint 和 reflow?
一個(gè)頁面由兩部分組成: DOM:描述該頁面的結(jié)構(gòu) render:描述 DOM 節(jié)點(diǎn) (nodes) 在頁面上如何呈現(xiàn)
當(dāng) DOM 元素的屬性發(fā)生變化 (如 color) 時(shí), 瀏覽器會(huì)通知 render 重新描繪相應(yīng)的元素, 此過程稱為 repaint。
如果該次變化涉及元素布局 (如 width), 瀏覽器則拋棄原有屬性, 重新計(jì)算并把結(jié)果傳遞給 render 以重新描繪頁面元素, 此過程稱為 reflow。
這兩個(gè)過程是很耗費(fèi)瀏覽器性能的, 從 IE 系列和 Chrome 渲染頁面速度上的差距即可看出渲染引擎計(jì)算對(duì)應(yīng)值和呈現(xiàn)并不一定高效, 而每次對(duì)元素的操作都會(huì)發(fā)生 repaints 或 reflow, 因此編寫 DOM 交互時(shí)如果不注意就會(huì)導(dǎo)致頁面性能低下. 頁面渲染的過程如下:
1.解析HTML代碼并生成一個(gè) DOM 樹。
2.解析CSS文件,順序?yàn)椋簽g覽器默認(rèn)樣式->自定義樣式->頁面內(nèi)的樣式。
3.生成一個(gè)渲染樹(render tree)。這個(gè)渲染樹和DOM樹的不同之處在于,它是受樣式影響的。它不包括那些不可見的節(jié)點(diǎn)。
4.當(dāng)渲染樹生成之后,瀏覽器就會(huì)在屏幕上“畫”出所有渲染樹中的節(jié)點(diǎn)。
2. 什么情況下會(huì)觸發(fā)瀏覽器的repaint/reflow?
除了頁面在首次加載時(shí)必然要經(jīng)歷該過程之外,還有以下行為會(huì)觸發(fā)這個(gè)行為: 引用: 1. DOM元素的添加、修改(內(nèi)容)、刪除( Reflow + Repaint) 2. 僅修改DOM元素的字體顏色(只有Repaint,因?yàn)椴恍枰{(diào)整布局) 3. 應(yīng)用新的樣式或者修改任何影響元素外觀的屬性 4. Resize瀏覽器窗口、滾動(dòng)頁面 5. 讀取元素的某些屬性(offsetLeft、offsetTop、offsetHeight、offsetWidth、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、 getComputedStyle()、currentStyle(in IE))
3. 怎么優(yōu)化?
1. 避免在document上直接進(jìn)行頻繁的DOM操作,如果確實(shí)需要可以采用off-document的方式進(jìn)行,具體的方法包括但不完全包括以下幾種:
引用: 1. 先將元素從document中刪除,完成修改后再把元素放回原來的位置 2. 將元素的display設(shè)置為”none”,完成修改后再把display修改為原來的值 3. 如果需要?jiǎng)?chuàng)建多個(gè)DOM節(jié)點(diǎn),可以使用DocumentFragment創(chuàng)建完后一次性的加入document
2. 集中修改樣式
引用: 1. 盡可能少的修改元素style上的屬性 2. 盡量通過修改className來修改樣式 3. 通過cssText屬性來設(shè)置樣式值
3. 緩存Layout屬性值
引用: 對(duì)于Layout屬性中非引用類型的值(數(shù)字型),如果需要多次訪問則可以在一次訪問時(shí)先存儲(chǔ)到局部變量中,之后都使用局部變量,這樣可以避免每次讀取屬性時(shí)造成瀏覽器的渲染。
4. 設(shè)置元素的position為absolute或fixed
引用: 在元素的position為static和relative時(shí),元素處于DOM樹結(jié)構(gòu)當(dāng)中,當(dāng)對(duì)元素的某個(gè)操作需要重新渲染時(shí),瀏覽器會(huì)渲染整個(gè)頁 面。將元素的position設(shè)置為absolute和fixed可以使元素從DOM樹結(jié)構(gòu)中脫離出來獨(dú)立的存在,而瀏覽器在需要渲染時(shí)只需要渲染該元素 以及位于該元素下方的元素,從而在某種程度上縮短瀏覽器渲染時(shí)間,這在當(dāng)今越來越多的Javascript動(dòng)畫方面尤其值得考慮。
5. 權(quán)衡速度的平滑
引用: 比如實(shí)現(xiàn)一個(gè)動(dòng)畫,以1個(gè)像素為單位移動(dòng)這樣最平滑,但reflow就會(huì)過于頻繁,CPU很快就會(huì)被完全占用。如果以3個(gè)像素為單位移動(dòng)就會(huì)好很多。
6. 不要用tables布局
引用: 不要用tables布局的另一個(gè)原因就是tables中某個(gè)元素一旦觸發(fā)reflow就會(huì)導(dǎo)致table里所有的其它元素 reflow。在適合用table的場(chǎng)合,可以設(shè)置table-layout為auto或fixed,這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響范圍
7. 不要在css里面寫expression
引用: 很多情況下都會(huì)觸發(fā)reflow,如果css里有expression,每次都會(huì)重新計(jì)算一遍
參考文章:
1. 如何減少瀏覽器repaint和reflow 2. Repaint, reflow/relayout, restyle 3. Reflows & Repaints: CSS Performance making your JavaScript slow? 4. Repaint 跟蹤瀏覽器的渲染[如果你的FF是3.5beta+監(jiān)聽網(wǎng)頁的重繪情況]
經(jīng)典論壇交流:http://bbs.blueidea.com/?3015796
本文鏈接:http://www.95time.cn/tech/web/2011/8365.asp
出處:藍(lán)色理想
責(zé)任編輯:bluehearts
◎進(jìn)入論壇網(wǎng)頁制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評(píng)論。
|