原文地址:http://www.cun-xu.cn/index.ph...php
在頁面的生命週期中,一些效果的交互都有可能發生重排(Layout
)和重繪(Painting
),這些都會使咱們付出高額的性能代價。
瀏覽器從下載文件至本地到顯示頁面是個複雜的過程,這裏包含了重繪和重排。一般來講,渲染引擎會解析HTML文檔來構建DOM樹,與此同時,渲染引擎也會用CSS解析器解析CSS文檔構建CSSOM樹。接下來,DOM樹和CSSOM樹關聯起來構成渲染樹(RenderTree
),這一過程稱爲Attachment
。而後瀏覽器按照渲染樹進行佈局(Layout
),最後一步經過繪製顯示出整個頁面。css
其中重排和重繪是最耗時的部分,一旦觸發重排,咱們對DOM的修改引起了DOM幾何元素的變化,渲染樹須要從新計算,
而重繪只會改變vidibility
、outline
、背景色等屬性致使樣式的變化,使瀏覽器須要根據新的屬性進行繪製。更比而言,重排會產生比重繪更大的開銷。因此,咱們在實際生產中要嚴格注意減小重排的觸發。瀏覽器
1.頁面第一次渲染
在頁面發生首次渲染的時候,全部組件都要進行首次佈局,這是開銷最大的一次重排。
2.瀏覽器窗口尺寸改變
3.元素位置和尺寸發生改變的時候
4.新增和刪除可見元素
5.內容發生改變(文字數量或圖片大小等等)
6.元素字體大小變化。
7.激活CSS僞類(例如::hover
)。
8.設置style屬性
9.查詢某些屬性或調用某些方法。好比說:緩存
offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeightdom
除此以外,當咱們調用getComputedStyle
方法,或者IE裏的currentStyle
時,也會觸發重排,原理是同樣的,都爲求一個「即時性」和「準確性」。ide
vidibility
、outline
、背景色等屬性的改變佈局
咱們應當注意的是:重繪不必定致使重排,但重排必定會致使重繪。性能
div.style.top = "10px"; div.style.bottom = "10px"; div.style.right = "10px"; div.style.left = "10px"; console.log(div.offsetWidth); console.log(div.offseHeight); console.log(div.offsetRight); console.log(div.offsetLeft);
原來的操做會致使四次重排和四次重繪,變換順序以後只會觸發一次重排
在第一個console
的時候,瀏覽器把以前上面四個寫操做的渲染隊列都給清空了。由於渲染隊列原本就是空的,因此剩下的console
並無觸發重排,僅僅拿值而已。字體
經過class
和cssText
進行集中改變樣式
未進行優化的代碼是這樣的:優化
//bad var left = 10; var top = 10; el.style.left = left + "px"; el.style.top = top + "px";
雖然如今大部分現代瀏覽器都會有Flush
隊列進行渲染隊列優化,可是有些老版本的瀏覽器好比IE6這樣的坑貨效率依然低下:
這時咱們就能夠經過上面所說的利用class
和cssText
屬性集中改變樣式
//good el.className += " className"; //or el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
// bad 強制刷新 觸發兩次重排 div.style.left = div.offsetLeft + 1 + 'px'; div.style.top = div.offsetTop + 1 + 'px'; // good 緩存佈局信息 至關於讀寫分離 var curLeft = div.offsetLeft; var curTop = div.offsetTop; div.style.left = curLeft + 1 + 'px'; div.style.top = curTop + 1 + 'px'; 複製代碼
一旦咱們給元素設置display:none
時,元素不會存在於渲染樹中,至關於將其從頁面「拿掉」,咱們以後的操做將不會觸發重排和重繪,這叫作DOM的離線化。
dom.display = 'none' // 修改dom樣式 dom.display = 'block' 複製代碼
dom
碎片,在它上面批量操做dom
,操做完成以後,再添加到文檔中,這樣只會觸發一次重排。position
屬性設置爲absolute
或fixed
position
屬性爲absolute
或fixed
的元素,重排開銷比較小,不用考慮它對其餘元素的影響
position
屬性爲absolute
或fixed
的元素上,這樣對其餘元素影響較小動畫效果還應犧牲一些平滑,來換取速度,這中間的度本身衡量:
好比實現一個動畫,以1個像素爲單位移動這樣最平滑,可是Layout
就會過於頻繁,大量消耗CPU資源,若是以3個像素爲單位移動則會好不少。
GPU 硬件加速是指應用 GPU 的圖形性能對瀏覽器中的一些圖形操做交給 GPU 來完成,由於 GPU 是專門爲處理圖形而設計,因此它在速度和能耗上更有效率。
GPU 加速一般包括如下幾個部分:Canvas2D,佈局合成, CSS3轉換(transition
s),CSS3 3D變換(transforms
),WebGL和視頻(video
)。
/* * 根據上面的結論 * 將 2d transform 換成 3d * 就能夠強制開啓 GPU 加速 * 提升動畫性能 */ div { transform: translate3d(10px, 10px, 0); }
娘滴,終於寫完了,肩膀子疼的我,得要得肩周炎了。