簡介:
整個在瀏覽器的渲染過程中(頁面初始化,用戶行為改變界面樣式,動畫改變界面樣式等)reflow(回流)和repaint(重繪) 會大大影響web性能,尤其是手機頁面。因此我們在頁面設計的時候要盡量減少reflow和repaint。
什么是reflow和repaint
reflow:例如某個子元素樣式發生改變,直接影響到了其父元素以及往上追溯很多祖先元素(包括兄弟元素),這個時候瀏覽器要重新去渲染這個子元素相關聯的所有元素的過程稱為回流。
reflow:幾乎是無法避免的。現在界面上流行的一些效果,比如樹狀目錄的折疊、展開(實質上是元素的顯示與隱藏)等,都將引起瀏覽器的 reflow。鼠標滑過、點擊……只要這些行為引起了頁面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會引起它內部、周圍甚至整個頁面的重新渲染。通常我們都無法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響着。
repaint:如果只是改變某個元素的背景色、文 字顏色、邊框顏色等等不影響它周圍或內部布局的屬性,將只會引起瀏覽器 repaint(重繪)。repaint 的速度明顯快於 reflow
下面情況會導致reflow發生:
1:改變窗口大小
2:改變文字大小
3:內容的改變,如用戶在輸入框中敲字
4:激活偽類,如:hover
5:操作class屬性
6:腳本操作DOM
7:計算offsetWidth和offsetHeight
8:設置style屬性
瀏覽器渲染:
- 瀏覽器渲染過程: DOM tree, CSS tree --> Render tree --> Paint
- DOM tree根節點為html
- 渲染從瀏覽器左上角到右下角
- 第一次打開頁面至少觸發一次重繪和回流, 結構如寬高位置變化時, 觸發reflow回流;非結構如背景色變化時, 觸發repaint重繪. 二者都會造成體驗不佳
- 如何減少重繪和回流?
-
- 通過classname或cssText一次性修改樣式, 而非一個一個改
-
- 離線模式: 克隆要操作的結點, 操作后再與原始結點交換, 類似於虛擬DOM
-
- 避免頻繁直接訪問計算后的樣式, 而是先將信息保存下來
-
- 絕對布局的DOM, 不會造成大量reflow
-
- p不要嵌套太深, 不要超過六層
減少回流的方式:
1:不要通過父級來改變子元素樣式,最好直接改變子元素樣式,改變子元素樣式盡可能不要影響父元素和兄弟元素的大小和尺寸
2:盡量通過class來設計元素樣式,切忌用style
3:實現元素的動畫,對於經常要進行回流的組件,要抽離出來,它的position屬性應當設為fixed或absolute
4:權衡速度的平滑。比如實現一個動畫,以1個像素為單位移動這樣最平滑,但reflow就會過於頻繁,CPU很快就會被完全占用。如果以3個像素為單位移動就會好很多。
5:不要用tables布局的另一個原因就是tables中某個元素一旦觸發reflow就會導致table里所有的其它元素reflow。在適合用table的場合,可以設置table-layout為auto或fixed,
6:這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響范圍。
7:css里不要有表達式expression
8:減少不必要的 DOM 層級(DOM depth)。改變 DOM 樹中的一級會導致所有層級的改變,上至根部,下至被改變節點的子節點。這導致大量時間耗費在執行 reflow 上面。
9:避免不必要的復雜的 CSS 選擇器,尤其是后代選擇器(descendant selectors),因為為了匹配選擇器將耗費更多的 CPU。
10: 盡量不要過多的頻繁的去增加,修改,刪除元素,因為這可能會頻繁的導致頁面reflow,可以先把該dom節點抽離到內存中進行復雜的操作然后再display到頁面上。
11:請求如下值offsetTop, offsetLeft, offsetWidth, offsetHeight,scrollTop/Left/Width/Height,clientTop/Left/Width/Height,瀏覽器會發生reflow,建議將他們合並到一起操作,可以減少回流的次數。如果我們要經常去獲取和操作這些值,則可以先將這些值緩存起來。
參考鏈接:
http://ued.alimama.com/front-end/quick-tips-among-yahoo-n-rules/
http://www.cnblogs.com/Peng2014/p/4687218.html