浏览器重绘和重排
本文地址: http://www.cnblogs.com/blackmanba/p/browser-repaint-reflow.html或者http://forkme.info/browser-repaint-reflow/, 轉載請注明源地址。
概述
重排, 顧名思義就是重新排版的意思; 重繪, 就是瀏覽器重新繪制。理解重排和重繪的含義十分重要, 因為在評審頁面交互效果的時候, 重繪和重排是必須考慮的因素。并不是說交互效果實現了就可以了, 必須同時考慮到這樣做會引發什么性能問題。也就是說, 瀏覽器在進行重繪和重排的時候是要付出高昂的性能代價的。
瀏覽器執行流程
瀏覽器每次從服務器下載完頁面后就會對頁面進行渲染(Render), 這里面就包含了重繪以及重排。每種瀏覽器雖然工作原理略有差別, 但也遵循以下流程: 瀏覽器引擎會解析HTML文檔來構建DOM樹。樹的每個節點都是標簽, 有大小邊距等等的屬性, 這是因為每個HTML元素都遵循盒子模型(隱藏元素不包括在文檔樹中, 瀏覽器不會將其渲染)。渲染樹構建完畢后, 瀏覽器就能夠確定每個元素的位置并將元素放到正確的位置上, 再根據樹節點的樣式屬性繪制出頁面元素。由于瀏覽器的流布局的方式, 對渲染樹的計算通常只需要遍歷一遍即可。但table及其內部元素除外, 可能需要執行多次計算才能確定好在渲染樹中的屬性, 這個過程通常要耗費3倍以上的時間。這也是我們要避免使用table標簽的其中一個原因。
觸發條件
重繪
重繪是元素改變外觀時所觸發的瀏覽器行為, 不包括修改元素的幾何屬性。例如改變visibility, outline, background等屬性。瀏覽器會根據新的屬性重新繪制, 使元素呈現新的外觀。重繪不一定會帶來新的布局, 并不一定伴隨著重排。
重排
DOM元素的幾何屬性變化
當DOM的幾何屬性變化時, 渲染樹中的相關節點就會失效, 瀏覽器會重新構建渲染樹中失效的節點。而且, 當前元素的重排也許會帶來相關元素的重排。例如, 容器節點渲染樹改變時, 會觸發子節點的重新計算, 也會觸發后續兄弟節點的重排, 祖先節點需要重新計算大小, 最后, 每個元素可能都會進行重繪。可見, 重排一定會引起重繪, 并且因為重排的元素很多, 導致重排從性能上來說比重繪更差。一個元素的重排通常都會帶來一系列反應, 甚至觸發整個文檔的重繪和重排, 性能代價是高昂的。
DOM樹的結構變化
當DOM樹的結構變化時, 例如節點的增加, 減少, 刪除, 也會觸發重排。瀏覽器引擎渲染DOM樹類似前序遍歷, 也就是說當前元素不會影響前面已經遍歷過的元素。所以, 如果在body前面插入一個元素, 就會導致整個文檔的重新渲染, 而在其后插入一個元素, 就不會影響到前面元素的布局。
獲取某些屬性
瀏覽器會對重排進行優化, 可能會等到有足夠數量的變化發生, 或者等到一定時間, 或者等一個線程結束, 再一起處理。這樣就只會發生一次重排。但如果渲染樹直接發生變化, 當獲取一些屬性時, 瀏覽器為了取得正確的值也會觸發重排。這樣就使得瀏覽器的優化失效。這些屬性包括: offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。所以,在多次使用這些值時應進行緩存。
其他: 比如改變元素的某些樣式, 調整瀏覽器窗口等等也會觸發重排。
最佳實踐
- 避免在document上直接進行頻繁的DOM操作, 如果確實需要可以采用off-document方式進行;
- 集中修改樣式
- 緩存layout屬性值
- 設置position為absolute或者fixed
- 權衡動畫速度和CPU性能
- 不要使用table布局
- 不要在css中寫expression
判別方式
如何判斷頁面重繪和重排的性能, 在google chrome 上可以使用Timeline面板, 具體使用請查看這篇文章
參考文章
- 頁面重構應注意的repaint和reflow
- 瀏覽器的重繪repaints與重排reflows
- 瀏覽器的渲染原理簡介
轉載于:https://www.cnblogs.com/blackmanba/p/browser-repaint-reflow.html
總結
- 上一篇: Oracle实例
- 下一篇: typedef函数指针使用方法