會的,頻繁觸發重繪與迴流,會致使UI頻繁渲染,最終致使js變慢。javascript
有兩個線程:一個線程JavaScript解析,一個線程是UI渲染,這兩個實際上是互斥的兩個線程。css
當javascript 線程運行的時候 ui 線程則會停止暫停,反之亦然。java
那這是爲何呢?web
緣由是,當ui 線程運行對頁面進行渲染的時候 js 腳本不免會涉及到頁面視圖上的一些樣式的改變,爲了使這個改變動加準確 js 腳本只好等待ui 線程渲染完成的時候纔去執行。canvas
因此當一個頁面的元素樣式改動頻繁的時候ui 線程就會持續渲染,形成js 代碼反應慢半拍,卡頓的狀況。瀏覽器
觸發頁面重佈局的屬性:
一、盒子模型相關屬性會觸發重佈局:width ,height,padding,margin,display,border-width,border,min-heigh。dom
二、定位屬性及浮動也會觸發重佈局:top,bottom,left,right,position,float,clearide
三、改變節點內部文字結構也會觸發重佈局:text-align,overflow-y,font-weight,overflow,font-family,line-height,vertival-align,white-space,font-size佈局
只觸發重繪的屬性:
color
border-style
border-radius
visibility
text-decoration
background
background-image
background-position
background-repeat
background-size
outline-color
outline
outline-style
outline-width
box-shadow性能
總結:迴流必將引發重繪,而重繪不必定會引發迴流
如今咱們知道了那些屬性會觸發迴流,那如何避免迴流呢?
其實有兩個方法:
第一,不使用以上能觸發圖層迴流的屬性,
第二,創建一個圖層,讓迴流在這些圖層裏面進行,限制迴流和重繪的範圍,減小瀏覽器的運算工做量
1. 獲取DOM後分割爲多個圖層
2. 對每一個圖層的節點計算樣式結果(Recalculate style--樣式重計算)
3. 爲每一個節點生成圖形和位置(Layout--迴流和重佈局)
4. 將每一個節點繪製填充到圖層位圖中(Paint Setup和Paint--重繪)
5. 圖層做爲紋理上傳至GPU
6. 符合多個圖層到頁面上生成最終屏幕圖像(Composite Layers--圖層重組)
將頻繁重繪迴流的DOM元素單獨做爲一個獨立圖層,那麼這個DOM元素的重繪和迴流的影響只會在這個圖層中。
如何手動建立圖層l兩種方法:
Chrome瀏覽器的more tools下面的Layers能查看圖層信息,rendering能查看瀏覽器頁面正在重繪的元素。
用圖層能夠減小重繪和迴流,可是圖層會有合成的消耗,所以二者之間須要一個balance!
1. 用translate替代top改變
2. 用opacity(不會觸發迴流,更不會觸發重繪,沒有paint的過程,由於paint的過程是生成圖層,可是opcacity其實是直接改變的圖層的alpha通道,因此不涉及圖層的重繪)替代visibility(會觸發重繪可是不會觸發迴流),可是要同時有translate3d 或 translateZ 這些能夠建立的圖層的屬性存在才能夠阻止迴流
3. 不要一條一條地修改 DOM 的樣式,預先定義好 class,而後修改 DOM 的 className
4. 把 DOM 離線後修改,好比:先把 DOM 給 display:none (有一次 Reflow),而後你修改100次,而後再把它顯示出來,若是確實須要用 js 對 dom 設置多條樣式那麼能夠將這個dom 先隱藏,而後再對其設置
5. 不要把 DOM 結點的屬性值放在一個循環裏當成循環裏的變量。瀏覽器有一個迴流的緩衝機制,即多個迴流會保存在一個棧裏面,當這個棧滿了瀏覽器便會一次性觸發全部樣式的更改且刷新這個棧。可是若是你屢次獲取這些元素的實際樣式,瀏覽器爲了給你一個準確的答案便會不停刷新這個緩衝棧,致使頁面迴流增長。因此爲了不這個問題,應該用一個變量保存在循環體外。
6. 不要使用 table 佈局,可能很小的一個小改動會形成整個 table 的從新佈局
7. 動畫實現的速度的選擇。動畫的時間間隔短,動畫連續,可是不斷的迴流重繪影響性能,動畫的時間長,動畫卡頓,性能會好點。
8. 對於動畫新建圖層,對於頻繁變化的元素應該爲其加一個 transform 屬性,對於視頻使用video 標籤
9. 啓用 GPU 硬件加速,經過設置transform:translateZ(0);transform: translate3d(0,0,0)