為什么會(huì)卡頓?
有一個(gè)前提必須要提,前端開(kāi)發(fā)者們都知道,瀏覽器是單線程運(yùn)行的。但是我們要明確以下幾個(gè)概念:?jiǎn)尉€程,主線程和合成線程。
雖然說(shuō)瀏覽器執(zhí)行js是單線程執(zhí)行(注意,是執(zhí)行,并不是說(shuō)瀏覽器只有1個(gè)線程,而是運(yùn)行時(shí),runing),但實(shí)際上瀏覽器的2個(gè)重要的執(zhí)行線程,這 2 個(gè)線程協(xié)同工作來(lái)渲染一個(gè)網(wǎng)頁(yè):主線程和合成線程。
一般情況下,主線程負(fù)責(zé):運(yùn)行 JavaScript;計(jì)算 HTML 元素的 CSS 樣式;頁(yè)面的布局;將元素繪制到一個(gè)或多個(gè)位圖中;將這些位圖交給合成線程。
相應(yīng)地,合成線程負(fù)責(zé):通過(guò) GPU 將位圖繪制到屏幕上;通知主線程更新頁(yè)面中可見(jiàn)或即將變成可見(jiàn)的部分的位圖;計(jì)算出頁(yè)面中哪部分是可見(jiàn)的;計(jì)算出當(dāng)你在滾動(dòng)頁(yè)面時(shí)哪部分是即將變成可見(jiàn)的;當(dāng)你滾動(dòng)頁(yè)面時(shí)將相應(yīng)位置的元素移動(dòng)到可視區(qū)域。
那么為什么會(huì)造成動(dòng)畫(huà)卡頓呢?
原因就是主線程和合成線程的調(diào)度不合理。
下面來(lái)詳細(xì)說(shuō)一下調(diào)度不合理的原因:
在使用height,width,margin,padding作為transition的值時(shí),會(huì)造成瀏覽器主線程的工作量較重,例如從margin-left:-20px渲染到margin-left:0,主線程需要計(jì)算樣式margin-left:-19px,margin-left:-18px,一直到margin-left:0,而且每一次主線程計(jì)算樣式后,合成進(jìn)程都需要繪制到GPU然后再渲染到屏幕上,前后總共進(jìn)行20次主線程渲染,20次合成線程渲染,20+20次,總計(jì)40次計(jì)算。
主線程的渲染流程,可以參考瀏覽器渲染網(wǎng)頁(yè)的流程:
使用 HTML 創(chuàng)建文檔對(duì)象模型(DOM)
使用 CSS 創(chuàng)建 CSS 對(duì)象模型(CSSOM)
基于 DOM 和 CSSOM 執(zhí)行腳本(Scripts)
合并 DOM 和 CSSOM 形成渲染樹(shù)(Render Tree)
使用渲染樹(shù)布局(Layout)所有元素
渲染(Paint)所有元素
也就是說(shuō),主線程每次都需要執(zhí)行Scripts,Render Tree ,Layout和Paint這四個(gè)階段的計(jì)算。
而如果使用transform的話,例如tranform:translate(-20px,0)到transform:translate(0,0),主線程只需要進(jìn)行一次tranform:translate(-20px,0)到transform:translate(0,0),然后合成線程去一次將-20px轉(zhuǎn)換到0px,這樣的話,總計(jì)1+20計(jì)算。
可能會(huì)有人說(shuō),這才提升了19次,有什么好性能提升的?
假設(shè)一次10ms。
那么就減少了約190ms的耗時(shí)。
會(huì)有人說(shuō),辣雞,才190ms,無(wú)所謂。
那么如果margin-left是從-200px到0呢,一次10ms,10ms
199≈2s。
還會(huì)有人說(shuō),辣雞,也就2s,無(wú)所謂。
你忘了單線程這回事了嗎?
2s=6s,就是6s的性能提升。
由于數(shù)據(jù)是猜測(cè)的,所以暫時(shí)不考慮其真實(shí)性
為了增強(qiáng)本文的說(shuō)服力,下面我就用一個(gè)實(shí)例來(lái)證實(shí)下我的觀點(diǎn),大家一起看一下
|
新聞熱點(diǎn)
疑難解答
圖片精選