滿足則不辱,知止則不殆。——老子javascript
大多數設備的刷新頻率是60Hz,也就說是瀏覽器對每一幀畫面的渲染工做要在 16ms 內完成,超出這個時間,頁面的渲染就會出現卡頓現象,影響用戶體驗。 repaint/重繪 和 reflow/迴流發生在什麼渲染的那個階段,咱們要了解什麼叫作 repaint/重繪和 reflow/迴流.java
repaint 就是在不影響排版的狀況下對這個元素從新繪製的過程。例如改變一個元素的背景顏色、字體顏色等。jquery
當 render tree 中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建。這就稱爲迴流(其實我以爲叫從新佈局更簡單明瞭些)。每一個頁面至少須要一次迴流,就是在頁面第一次加載的時候。 迴流必將引發重繪,而重繪不必定會引發迴流chrome
1. JS/CSS>計算樣式>佈局>繪製>渲染層合併瀏覽器
2. JS/CSS>計算樣式>繪製>渲染層合併 緩存
3. JS/CSS>計算樣式>渲染層合併 dom
上面大體已經記錄了 repaint、reflow 的流程和爲何要關注它,下面記錄一下它們的觸發條件、和 eventLoop 的關係。
上面大體就是觸發repaint、reflow的操做,還有更多的後面還會補全。
在這個裏面記錄了觸發 repaing、reflow,還有和 eventloop 的關係,可是 eventloop 和 ui 渲染流程關係有點太複雜,因此大體記錄了一下。
動畫實現,避免使用 setTimeout 或 setInterval,儘可能使用 requestAnimationFrame 把耗時長的 JavaScript 代碼放到 Web Workers 中去作
動畫實現,避免使用 setTimeout 或 setInterval,儘可能使用 requestAnimationFrame setTimeout(callback)和 setInterval(callback)沒法保證 callback 函數的執行時機,極可能在幀結束的時候執行,從而致使丟幀,以下圖:
requestAnimationFrame(callback)能夠保證 callback 函數在每幀動畫開始的時候執行。
注意:jQuery 的 animate 函數就是用 setTimeout 來實現動畫,能夠經過 jquery-requestAnimationFrame 這個補丁來用 requestAnimationFrame 替代 setTimeout
把耗時長的 JavaScript 代碼放到 Web Workers 中去作 JavaScript 代碼運行在瀏覽器的主線程上,與此同時,瀏覽器的主線程還負責樣式計算、佈局、繪製的工做,若是 JavaScript 代碼運行時間過長,就會阻塞其餘渲染工做,極可能會致使丟幀。 前面提到每幀的渲染應該在 16ms 內完成,但在動畫過程當中,因爲已經被佔用了很多時間,因此 JavaScript 代碼運行耗時應該控制在3-4 毫秒。
用戶輸入事件處理函數會在運行時阻塞幀的渲染,而且會致使額外的佈局發生。 理想狀況下,當用戶和頁面交互,頁面的渲染層合併線程將接收到這個事件並移動元素。這個響應過程是不須要主線程參與,不會致使 JavaScript、佈局和繪製過程發生。
可是若是被觸摸的元素綁定了輸入事件處理函數,好比 touchstart/touchmove/touchend
,那麼渲染層合併線程必須等待這些被綁定的處理函數執行完畢才能執行,也就是用戶的滾動頁面操做被阻塞了,表現出的行爲就是滾動出現延遲或者卡頓。 簡而言之就是你必須確保用戶輸入事件綁定的任何處理函數都可以快速的執行完畢,以便騰出時間來讓渲染層合併線程完成他的工做。
輸入事件處理函數,好比 scroll/touch 事件
的處理,都會在 requestAnimationFrame
以前被調用執行。 所以,若是你在上述輸入事件的處理函數中作了修改樣式屬性的操做,那麼這些操做就會被瀏覽器暫存起來,而後在調用 requestAnimationFrame
的時候,若是你在一開始就作了讀取樣式屬性的操做,那麼將會觸發瀏覽器的強制同步佈局操做。
經過 requestAnimationFrame 能夠對樣式修改操做去抖動,同時也可使你的事件處理函數變得更輕
function onScroll(evt) {
// Store the scroll value for laterz.
lastScrollY = window.scrollY;
// Prevent multiple rAF callbacks.
if (scheduledAnimationFrame) {
return;
}
scheduledAnimationFrame = true;
requestAnimationFrame(readAndUpdatePage);
}
window.addEventListener("scroll", onScroll);
複製代碼
使用 Chrome DevTools 來了解頁面的渲染層狀況
經過 Chrome DevTools 的 Preformance 來錄製一段操做,而且開啓 More tools 的 Layers、Rendering 功能,若是下圖所示:
能夠用 preformance 對象來作一些前端的性能分析和統計,以下圖所示:
在這個上面瞭解了 reflow、repaint
的流程和他的觸發條件,再後面也有一部分怎麼優化性能,結合前面的渲染流程大體知道優化的是那部分的流程。固然在優化性能的時候,必定要結合 chrome 的性能分析功能。