DOM樹和樣式結構體 (瀏覽器所能識別的所有樣式) 構建組成渲染樹 (render tree) 來完成繪製頁面
當渲染樹的一部分發生改變, 若只引起頁面的非佈局外觀 (如背景等) 發生改變時, 那這就是一次頁面重繪(repaint);
若引起頁面的佈局發生改變, 那這就是一次頁面迴流 (reflow), 同時頁面外觀也發生改變, 意味着必然伴隨重繪
從定義中可知何時會發生重繪與迴流
迴流
添加/刪除元素
display: none;
定位, 浮動, 邊距等改變位置
改變盒模型
改變文字大小, 粗細, 位置, 間隔, 行高, 超出容器處理方式等
改變瀏覽器大小
激活僞類 (:hover)
內容變化 (input等輸入文字)
重繪
改變 visiblility: hidden; z-index, 輪廓, 顏色, 背景, 陰影, 倒影等
迴流的代價遠比重繪昂貴, 很大程度影響着頁面性能, 減緩JavaScript
減少迴流次數: 在頁面加載時, 瀏覽器會把所有引起迴流的操作在構建渲染樹前排入一個隊列, 並在出隊列時批量處理,
然後執行一次頁面繪製, 使這過程只發生一次迴流當需要訪問佈局上的迴流數據,
如窗口大小等, 樣式中的盒模型, 偏移量等屬性, 瀏覽器就會將這些迴流操作提前處理一遍, 並執行一次頁面繪製,
然後提供相關數據, 從而增加了一次頁面迴流
變量存儲:
如果多次訪問佈局上的相同迴流數據, 那麼迴流次數就增加了可以將要訪問的相同數據存儲爲變量到內存, 然後再次訪問相同數據時, 只要讀取內存中的變量即可
避免用類名或樣式屬性來作爲條件判斷的依據
封裝樣式:
將需要改變的多個樣式封裝到一個類裏, 然後只要改變className
若樣式的屬性值是動態的, 則用cssText, 如 element.syle.cssText +=';width: ' + 動態寬度變量 + 'px; height: ' + 動態高度變量 + 'px;';
img設置寬高, 避免頁面加載後, 再爲圖片文件繪製寬高, 而產生迴流
減小回流範圍: 把引起迴流的操作在構建渲染樹或改變渲染樹的一部分前進行批量處理, 然後執行一次頁面繪製
添加多個節點時, 在還沒添加到DOM前, 先把多個節點放到一個節點中, 然後只要把這樣一個節點添加到DOM中, 使迴流只發生在一個節點上
對元素進行多次操作前, 先用display: none; 讓該元素離開DOM, 然後在操作結束後顯示元素使迴流只發生兩次
在其他節點後面添加節點或改變樣式, 只會自身產生迴流; 在其他節點前添加節點或改變樣式, 可能導致其他節點都產生迴流
通過定位改變位置, 只會自身產生迴流; 通過邊距改變位置, 可能使其他節點也產生的迴流
避免使用table和多層嵌套
避免在樣式中用 expression(eval(...));
CPU優化: 瀏覽器會在主線程外爲執行CSS3動畫的節點創建一個圖層, 並把節點移到圖層上,
然後通過CPU或GPU將同一個動畫的每個節點所創建的圖層組合成一個圖層添加到頁面, 最後執行動畫
這過程把節點移到圖層上時產生了一個迴流, 這個迴流讓同一個動畫的每個節點都消失;
把圖層添加到頁面又產生了一個迴流, 這個迴流花費的時間基本決定了動畫開始前的準備時間,
如果所花的時間較長, 就會看到這些節點消失的瞬間, 如果用CPU處理 (CPU處理圖層不及GPU), 所花的時間會更長
綜上可知, transform 和 opacity 的動畫過程沒有迴流, 但動畫前卻是一場噩夢
開啓設備硬件加速渲染, 即強制使用GPU進行2D繪圖
用 translateZ() 或 translate3d() 代替 translate() 從而提高CPU的處理減少動畫開始前的準備時間, 且不會隨着抗鋸齒而導出突變,
但依舊免不了迴流所耗的時間, 而且過多 translateZ() 或 translate3d() 佔用CPU使用率, 將導致CPU性能下降
-webkit-font-smoothing: antialiased/subpixel-antialiased; 抗鋸齒緩解字體變虛
-webkit-backface-visibility: hidden; 解決rotate發生衝突而閃動
犧牲平滑度換取速度
每次1px移動一個動畫, 可能導致動畫及隨後的迴流佔用了很高的CPU使用率, 動畫就會看上去是跳動的,
因爲瀏覽器正在與更新迴流做鬥爭動畫元素每次移動3px可能在非常快的機器上看起來平滑度低了,
但它不會導致在CPU較慢的機器和移動設備中抖動