應該知道的前端效能二三事 —— Reflow 和 Repaint
移動 Web 前端開發,目前是火的不能再火了。到處都在招什麼 H5 工程師、Hybrid App 開發工程師,主要負責的其實就是一些移動 Web 前端開發的工作。稍微有過一些前端經驗的人都知道,手機上的開銷比 PC 上要大的多,你在 PC 的模擬器上除錯的很順暢,等到手機上時,就會卡,這是為什麼呢?其實這就是效能問題,有其他的開銷佔用了你的計算資源啦,那麼是哪些開銷佔用了呢?拋開後端介面慢啊、網路狀態差啊什麼的不說,我們們今天聊聊瀏覽器本身的細節,Reflow 和 Repaint。尤其是在新增一些 CSS3 動畫或者批量操作多個 DOM 元素的時候,Reflow 和 Repaint 的影響就會更加大。
啥是 Reflow 和 Repaint
Repaint
Repaint 就是「重繪」,它會在你改變 DOM 元素的視覺效果時進行,改變佈局時不會觸發。比如,opacity,background-color,visibility和outline等都會觸發,「重繪」的開銷還是比較昂貴的,因為瀏覽器會在某一個 DOM 元素的視覺效果改變後去 check 這個 DOM 元素內的所有節點。
Reflow
Reflow 就是「迴流」,它的影響更大。它會在某一個 DOM 元素的位置發生改變後觸發,而且它會重新計算所有元素的位置和在頁面中的佔有的面積,這樣的話將會引起頁面某一個部分甚至整個頁面的重新渲染。改變某一個元素會影響它所有的子節點 (children)、祖先節點 (ancestors) 及兄弟節點(siblings)。
Reflow 和 Repaint 都是瀏覽器慢的元凶
Reflow 的開銷更加昂貴,那麼具體哪些時候會觸發 Reflow?
新增、刪除或者改變 DOM 元素的可見性時:使用 JS 去改變 DOM 元素時會觸發 Reflow。
新增、刪除或者改變 CSS 樣式:直接改變 CSS Style 或者元素的 class 可能會影響佈局,還有改變一個元素的寬度能夠影響它所在的 DOM 節點中的所有元素,以及它周圍的那些元素。
CSS3 動畫(animation)和過渡(transition): 動畫的每一 frame 都會觸發 Reflow。
使用 offsetWidth 和 offsetHeight:這一點很特別,你讀一個 DOM 的 offsetWidth 和 offsetHeight 屬性同樣會觸發一下 Reflow,因為這兩個屬性需要依賴一些元素去計算。
使用者互動:使用者可以通過 hover 一下 a 連結,在 input 裡面輸入文字,拖動瀏覽器的大小,改變字型大小,更換樣式表或者字型等都會觸發 reflow。
一些常用的提高效能的原則
佈局
不要用inline style
或 table 佈局,flexbox
佈局也會給效能帶來一些小困擾。inline style
會在 html 下載完後進行一次額外的 Reflow,table佈局的開銷遠比其他 DOM 元素的佈局開銷要大。flexbox
的item
會在 HTML 下載完成後改變尺寸。
簡寫 CSS
儘量簡寫 CSS,避免使用複雜的 CSS 選擇器,使用 UnusedCSS, uCSS, gulp-uncss可以有效的減少樣式的定義和檔案的大小。
優化 DOM
減少 DOM 的層級,減少 DOM 的數量,如果不需適配老瀏覽器,刪掉一些無用的 wrapper 性質的 DOM 元素,總之越少越好。
慎改 class
在一個 DOM 樹中,儘可能改那些沒有特別多子元素 DOM 的 class,子元素少的可以改,多的不推薦。
避免複雜動畫
刪掉複雜的動畫,運用動畫的元素儘量是 position:absolute 或 position:fixed 的,這樣會讓他們脫離文件流,不去影響其他的元素。
善用 display:none
display:none
的元素不會引發 Reflow 和 Repaint,可以在讓這些元素在 display 之前進行一些諸如顏色、尺寸什麼的改變。
避免大量 DOM 互相影響
比如 Tabs 這種場景,如果你點選一個 Tab 會顯示它控制的區塊,顯示的那個區塊會影響其他的區塊,這樣可能會引起 Reflow,因為它們的高度不一樣,可以通過定個高度來優化這種場景。
效能永遠比酷炫重要
記住一個原則,你網頁的動畫再牛逼,效能還是第一位的,如果每一幀移動1個畫素會造成你的頁面卡頓,那寧願每一幀移動10畫素讓動畫的幀變得遲鈍一些,也不要讓頁面的效能降下來。
相關文章
- reflow和repaint引發的效能問題AI
- Reflow & RepaintAI
- BFC!Repaint!ReflowAI
- 【前端工程師手冊】學習迴流和重繪(reflow和repaint)前端工程師AI
- 迴流(reflow)與重繪(repaint)AI
- 前端應該知道的GraphQL前端
- 瀏覽器的迴流與重繪 (Reflow & Repaint)瀏覽器AI
- 前端正則二三事前端
- 你應該知道的Redis事務Redis
- 前端渲染過程的二三事前端
- 前端應該知道的web登入前端Web
- 你應該知道的前端--渲染原理前端
- 你應該知道的前端--儲存前端
- 你應該知道的前端——快取前端快取
- 你必須要知道的babel二三事Babel
- 關於Git小白應該知道的事Git
- 那些前端應該知道的HTTP知識前端HTTP
- 前端開發者應該知道的 CSS 小技巧前端CSS
- Function和Object 應該知道的FunctionObject
- 你應該知道的關於SEO和Javascript的6個事實JavaScript
- 什麼是重繪repaint?什麼是迴流reflow?AI
- 關於前端架構師的二三事前端架構
- 關於前端模組化你應該知道的前端
- 每個前端應該知道的jquery 細節前端jQuery
- DOM和Diff演算法你應該知道的那些事,快收藏!演算法
- 用友雲開發者中心,你應該知道的那些事
- IT職場:每個黑帶都應該知道的事
- 三件Java開發者應該知道的事兒Java
- 推薦Web前端初學者應該知道的書籍和網站!Web前端網站
- 最大限度的減少瀏覽器的重新佈局(Reflow&Repaint)瀏覽器AI
- 前端工程師應該知道的yarn知識前端工程師Yarn
- 服務端效能測試你應該知道的服務端
- CSS 和 JS 阻塞二三事CSSJS
- 淺談AsyncLocal,我們應該知道的那些事兒
- 關於MySQL密碼你應該知道的那些事MySql密碼
- 軟體工程師應該知道的9件事軟體工程工程師
- 關於 MySQL 密碼你應該知道的那些事MySql密碼
- 程式設計師應該知道的97件事程式設計師