我們經(jīng)常說到瀏覽器的性能問題,其實與瀏覽器性能息息相關的一點就是瀏覽器如何渲染我們的網(wǎng)頁,這個時候我們就會涉及到一個概念,那就是瀏覽器的回流(重排,以下統(tǒng)稱回流,Reflow)與重繪(Repaint)。
回流
對回流這個詞,我的理解是回爐重造,即對于整個網(wǎng)頁重新渲染一遍。那我們可以思考一下,從性能角度來講,如果我們來寫瀏覽器的代碼,一定是再必須要重新渲染網(wǎng)頁的時候再重新渲染,那就推出一個問題,什么時候瀏覽器必須要重新渲染網(wǎng)頁?
其實必定是當網(wǎng)頁的元素坐標發(fā)生變化的時候,這里我們可以理解為有很多人在排隊,大家僅僅的依靠在一起,那什么時候大家需要都挪動下位置呢?我覺得要么就是一個人或者幾個人突然變胖了/瘦了,那大家如果想要繼續(xù)依靠在一起,就得都動一動;或者其中一個人或者幾個人挪動了一下自己的位置,他勢必也會擠著其他人去動一動位置。這種重新渲染全部或部分文檔的動作我們就叫做回流,因為大家都需要挪動下位置,也就導致我們這個網(wǎng)頁需要回爐重造了。
所以會導致回流的操作(包括但不限于):
頁面首次渲染
瀏覽器窗口大小發(fā)生改變
元素尺寸或位置發(fā)生改變
元素內(nèi)容變化(文字數(shù)量或圖片大小等等)
元素字體大小變化
添加或者刪除可見的
DOM元素激活
CSS偽類(例如::hover)
重繪
還是拿排隊舉例,當隊伍中的一個人需要換一件衣服,比如他從穿黃衣服換成穿紅色的衣服,這個時候只要這一個人換件衣服就行了,對其他人并沒有影響,這種情況我們就叫做重繪。瀏覽器只需要對該元素進行重新繪制即可。
所以會導致回流的操作(包括但不限于):
- 修改color/background-color/visibility
由上述可見,其實回流對瀏覽器性能的消耗是高于重繪的,而且回流的操作一定會伴隨著重繪,重繪卻不一定伴隨回流。那現(xiàn)代瀏覽器其實對這塊是有進行優(yōu)化處理的,如果我們的隊伍總是需要變換位置,我們就統(tǒng)一來一次大排隊。
那么我們在平時的工作中,如果針對于回流和重繪寫出性能更好地代碼呢?有以下幾點可以注意的:
CSS
避免使用
table布局。盡可能在
DOM樹的最末端改變class。避免設置多層內(nèi)聯(lián)樣式。
將動畫效果應用到
position屬性為absolute或fixed的元素上。避免使用
CSS表達式(例如:calc())。
JavaScript
避免頻繁操作樣式,最好一次性重寫
style屬性,或者將樣式列表定義為class并一次性更改class屬性。避免頻繁操作
DOM,創(chuàng)建一個documentFragment,在它上面應用所有DOM操作,最后再把它添加到文檔中。也可以先為元素設置
display: none,操作結(jié)束后再把它顯示出來。因為在display屬性為none的元素上進行的DOM操作不會引發(fā)回流和重繪。避免頻繁讀取會引發(fā)回流/重繪的屬性,如果確實需要多次使用,就用一個變量緩存起來。
對具有復雜動畫的元素使用絕對定位,使它脫離文檔流,否則會引起父元素及后續(xù)元素頻繁回流。
參考 瀏覽器的回流與重繪 (Reflow & Repaint)
博客地址 北落師門