【前端優化之渲染優化】大屏android手機動畫丟幀的背後

前言

上週我與阿里的宇果有一次技術的交流,而後對天貓H5站點作了一些淺層次的分析,後面點時間基本每天都會有聯繫,中途聊了一些技術細節、聊了雙方團隊在幹什麼,最後聊到了前端優化。由於我自己參與了幾回攜程H5站點的優化,在這方面有一些心得,可是與宇果交流的過程當中發現咱們在優化的時候忽略了一些細節。javascript

攜程作優化的時候整個重心基本放到了尺寸的縮減,和宇果的交流過程當中他提出了渲染優化,其實渲染優化無非是減小回流,對於減小回流咱們也有一些概念,我一直認爲這個事情應該業務開發關注而不是框架關注(事實上框架也沒法關注),因此對一些BUG採起了表現層面的解決,卻對真相視而不見的作法,如今想來真的有點無知,這裏便以一個原來的渲染BUG爲切入點,將最近與宇果的交流所得整理下。css

宇果博客:http://www.ghugo.com/html

迴流與重繪

首先,咱們再次複習一下回流與重繪的知識,瀏覽器會解析三個東西:HTML、Javascript、CSS。前端

瀏覽器首先會根據HTML生成DOM Tree,其次會根據CSS生成CSS Rule Tree,javascript能夠經過DOM API與CSS API操做DOM Tree與CSS Rule Tree,從而引發頁面變化。java

瀏覽器解析結束會經過DOM Tree與CSS Rule Tree造成render tree,只有display不爲none的元素纔會造成render Tree,render Tree造成後瀏覽器會調用GUI繪製頁面,在此以前作的一件事情即是layout或者說reflow。上面的描述簡單而言能夠分爲如下流程:android

l  生成DOM樹css3

l  計算CSS樣式web

l  構建render treechrome

l  reflow,定位元素位置大小瀏覽器

l  繪製頁面

在這個過程當中,如果javascript動態改變DOM Tree便會引發reflow

頁面中的元素改變,只要不影響尺寸,好比只是顏色改變只會引發repaint不會引發迴流

不然,reflow不可避免,這個時候便須要從新計算造成render Tree

reflow分爲局部迴流與全局迴流,會影響下面的,不會影響上面的元素

reflow耗用的系統資源較大,DOM Tree中受到影響的節點皆會reflow,而後影響其子節點最壞的狀況是全部節點reflow,該問題引起的現象即是低性能的電腦風扇不停的轉,手機變得很熱,而且很是耗電,如下操做可能引發reflow

l  操做dom結構

l  動畫

l  DOM樣式修改

l  獲取元素尺寸的API

android大屏手機渲染BUG

這個是咱們一個tab組件,這個組件按道理說很是簡單:

 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4   <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
 5   <title></title>
 6   <style type="text/css">
 7     body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
 8     
 9     ul, ol { list-style: none; margin: 0; padding: 0; }
10     
11     .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
12     
13     .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
14     
15     .cui-tab-mod li.cui-tab-current { color: #099fde; }
16     
17     .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease-in-out; -moz-transition: -moz-transform 300ms ease-in-out; -ms-transition: -ms-transform 300ms ease-in-out; transition: transform 300ms ease-in-out; z-index: -1; }
18     
19     .cui-tabnum2 { width: 50%; }
20     
21     .cui-tabnum3 { width: 33.33333%; }
22     
23     .cui-tabnum4 { width: 25%; }
24     
25     .cui-tabnum5 { width: 20%; }
26     
27     .cui-tabnum6 { width: 16.66666%; }
28     
29     .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
30     
31     .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }
32     
33     .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); }
34     
35     .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); }
36     
37     .cui-tab-mod li:nth-of-type(4).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(300%,0,0); -moz-transform: translate3d(300%,0,0); -ms-transform: translate3d(300%,0,0); transform: translate3d(300%,0,0); }
38     
39     .cui-tab-mod li:nth-of-type(5).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(400%,0,0); -moz-transform: translate3d(400%,0,0); -ms-transform: translate3d(400%,0,0); transform: translate3d(400%,0,0); }
40     
41     .cui-tab-mod li:nth-of-type(6).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(500%,0,0); -moz-transform: translate3d(500%,0,0); -ms-transform: translate3d(500%,0,0); transform: translate3d(500%,0,0); }
42   </style>
43   <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
44 </head>
45 <body>
46 
47   <ul class="cui-tab-mod">
48     <li data-key="0" data-index="0" class="cui-item cui-tab-current">中國</li>
49     <li data-key="1" data-index="1" class="cui-item">美國</li>
50     <li data-key="2" data-index="2" class="cui-item">日本</li>
51     <i class="cui-tab-scrollbar cui-tabnum3"></i>
52   </ul>
53   <script type="text/javascript">
54     $(function () {
55       var wrapper = $('.cui-tab-mod');
56       wrapper.on('click', function (e) {
57         var el = $(e.target);
58         if (el.hasClass('cui-item')) {
59           wrapper.find('li').removeClass('cui-tab-current');
60           el.addClass('cui-tab-current');
61         }
62       });
63     });
64   </script>
65 </body>
66 </html>
View Code

點擊一下就讓當前item獲取class,而後文字樣式會改變,下面一個橫線也會動畫滑動過去,可是這個東西在android大屏手機上卻出了問題(好比note2),他會這樣表現:

如圖所示,class過去了,文字顏色也變了,可是下面對應的豎條卻沒有過去,我當時一看就知道是渲染的問題而且立刻給出了一個解決方案:

 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4   <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
 5   <title></title>
 6   <style type="text/css">
 7     body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
 8     
 9     ul, ol { list-style: none; margin: 0; padding: 0; }
10     
11     .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
12     
13     .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
14     
15     .cui-tab-mod li.cui-tab-current { color: #099fde; }
16     
17     .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease-in-out; -moz-transition: -moz-transform 300ms ease-in-out; -ms-transition: -ms-transform 300ms ease-in-out; transition: transform 300ms ease-in-out; z-index: -1; }
18     
19     .cui-tabnum2 { width: 50%; }
20     
21     .cui-tabnum3 { width: 33.33333%; }
22     
23     .cui-tabnum4 { width: 25%; }
24     
25     .cui-tabnum5 { width: 20%; }
26     
27     .cui-tabnum6 { width: 16.66666%; }
28     
29     .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
30     
31     .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }
32     
33     .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); }
34     
35     .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); }
36     
37     .cui-tab-mod li:nth-of-type(4).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(300%,0,0); -moz-transform: translate3d(300%,0,0); -ms-transform: translate3d(300%,0,0); transform: translate3d(300%,0,0); }
38     
39     .cui-tab-mod li:nth-of-type(5).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(400%,0,0); -moz-transform: translate3d(400%,0,0); -ms-transform: translate3d(400%,0,0); transform: translate3d(400%,0,0); }
40     
41     .cui-tab-mod li:nth-of-type(6).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(500%,0,0); -moz-transform: translate3d(500%,0,0); -ms-transform: translate3d(500%,0,0); transform: translate3d(500%,0,0); }
42   </style>
43   <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
44 </head>
45 <body>
46 
47   <ul class="cui-tab-mod">
48     <li data-key="0" data-index="0" class="cui-item cui-tab-current">中國</li>
49     <li data-key="1" data-index="1" class="cui-item">美國</li>
50     <li data-key="2" data-index="2" class="cui-item">日本</li>
51     <i class="cui-tab-scrollbar cui-tabnum3"></i>
52   </ul>
53   <script type="text/javascript">
54     $(function () {
55       var wrapper = $('.cui-tab-mod');
56       wrapper.on('click', function (e) {
57         var el = $(e.target);
58         var toolBar = $('.cui-tab-scrollbar');
59         if (el.hasClass('cui-item')) {
60           wrapper.find('li').removeClass('cui-tab-current');
61           el.addClass('cui-tab-current');
62           setTimeout(function () {
63             toolBar.width('width', toolBar.width());
64           }, 0)
65         }
66       });
67     });
68   </script>
69 </body>
70 </html>
View Code

這裏設置下劃線width的時候觸發了其迴流,而setTimeout會在主程序執行結束後才觸發,因而BUG修復了,核心代碼以下:

 1 $(function () {
 2   var wrapper = $('.cui-tab-mod');
 3   wrapper.on('click', function (e) {
 4     var el = $(e.target);
 5     var toolBar = $('.cui-tab-scrollbar');
 6     if (el.hasClass('cui-item')) {
 7       wrapper.find('li').removeClass('cui-tab-current');
 8       el.addClass('cui-tab-current');
 9       //修復丟幀問題
10       setTimeout(function () {
11         toolBar.width('width', toolBar.width());
12       }, 0)
13     }
14   });
15 });

這個BUG解決後也沒有再關注,時序紛飛,一年過去了卻和宇果聊天過程當中再次想起這個問題,才意識到本身忽略的是什麼。

從新認識Timeline

咱們經常有一個問題,如何知道頁面哪裏的渲染有問題,如何捕捉?

若是沒有一個實際可用的工具的話,咱們只能由外文或者博客獲取這類知識,這個時候就和我解決上述問題差很少了,僅僅從皮毛上知道是渲染致使的問題,而且能使用迴流解決問題,倒是對渲染性能形成負擔,因此如何捕捉渲染問題衡量渲染性能這個是第一位,好在chrome提供了Timeline:

以咱們的頁面爲例,咱們開始監控,這裏稍微改變一下代碼:

 1 var wrapper = $('.cui-tab-mod');
 2 wrapper.on('click', function (e) {
 3   var el = $(e.target);
 4   var toolBar = $('.cui-tab-scrollbar');
 5   if (el.hasClass('cui-item')) {
 6     wrapper.find('li').removeClass('cui-tab-current');
 7     el.addClass('cui-tab-current');
 8 //      setTimeout(function () {
 9 //        toolBar.width('width', toolBar.width());
10 //      }, 0)
11   }
12 });
13 
14 function setIndex(i) {
15   var els = wrapper.find('li');
16   els.removeClass('cui-tab-current');
17   els.eq(i).addClass('cui-tab-current');
18 }

我首先點擊開始監控,而後鼠標不在頁面作任何操做,在控制檯輸入一句:

setIndex(1)

因而頁面會發生改變,這個時候,咱們獲得的圖是:

這張圖其實最初我也是看熱鬧的,昨天根據宇果的指點,才稍微看出點門道了:

首先請看上圖中的一個個透明框,每一個透明框即是兩次顯示器刷新週期中等待的時間,其中有一個很是關鍵的單位叫作fps,這個60fps是個什麼東西呢?

60fps與16ms

所謂60fps即是說屏幕1s會刷新60次,意思是大概16.5ms屏幕會刷新一次,在這一次刷新中瀏覽器會幹不少事情,這裏仍是以圖示爲例,這裏有2個前提:

① 咱們鼠標並未操做

② 咱們頁面很單一

因此在咱們執行setIndex前,瀏覽器根本沒有任何消耗,每一次的刷新干了這幾件事情:

剛剛整個過程一過通過了2.29秒,瀏覽器發生了這些事情:

從白條來看,瀏覽器處理整個動做大概花費320ms,這裏出了4種顏色,這個也比較關鍵。

4種顏色

黃色是說明正在執行javascript腳本,從這裏能夠看出,js執行的速度是很是快的,這裏包含了設值class、移除class,獲取width等一系列操做,瀏覽器會等一次結束後才發生渲染。

紫色是說明正在迴流,也就是咱們傳說中的渲染,這個是很是耗費性能的,咱們這裏具體跟進去看看:

接下來觸發了css3過渡transition的動畫,下面的滾動條開始了不停的移動:

能夠看到,後續全部的運動隻影響了一個元素,這個元素即是滾動條,這裏爲了驗證剛剛所說,咱們作兩個事情:

① 使用click觸發索引更改

② 爲下劃線添加子元素

這裏有個很是不一樣的就是,我鼠標在界面操做了,不可避免的會引發一些move樣式改變,因此有重繪有迴流,都比較輕,比較關鍵的是,其中多了一個click操做(Event),可是下面動畫時候影響的元素仍然只是一個,這個有點不明緣由,我這裏特別將transform改爲了left,由於transform更加平滑,我想找出緣由,卻發現了另外一個現象:

能夠看出transformd致使的動畫只會執行一次paint,即是最初那一次,而使用left的話卻在不停的paint,這個是資源消耗的對比:

能夠看出,使用left時候出現了鋸齒狀,這個時候咱們能夠得出一個結論,transform的動畫確實比left節省性能。

至此咱們對chrome的Timeline有了一個新的認識,可是咱們這裏的觀察所有是在PC端發生的,而手機端是怎麼樣的呢?

移動端的渲染

這個圖與上圖造成了鮮明對比,PC端就只有很小的波動,手機端卻引發了不少漣漪,致使這個問題的緣由是硬件設施(這裏是盜圖):

PS:這裏苦於沒有Android設備,chrome電腦又暫時抽風不能真機調試,便去同事那裏草草截圖,哎......

丟幀的發生

如前所述,瀏覽器一次的刷新約16ms,以一次原子行爲來講是這樣的:

腳本運行時間+渲染時間+繪製時間<16ms

若是中間有一次的操做好比渲染的時間大於了16ms而致使瀏覽器沒有來得及繪製,那麼那次的操做便失效了,這個就是所謂的丟幀。

咱們在note2上運行程序時會致使丟幀,應該就是其中一次超出了時限,由於class變化會引發樣式從新計算,可是隻是文字變化的話只是會引發重繪,因此主要問題發生在transition動畫。

而咱們的解決方案是setTimeout,這個形成的影響是:

咱們發現了,就算沒有動畫,從新計算樣式那裏依舊是主要致使的迴流的因素,是他擠掉了後續的操做嗎?他從新計算樣式中的因素有不少,我懷疑的目光首先放到了這段css:

    .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); 
-moz-transform
: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }

測試下來,彷佛與他相關:

 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4   <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
 5   <title></title>
 6   <style type="text/css">
 7     body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
 8     ul, ol { list-style: none; margin: 0; padding: 0; }
 9     .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
10     .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
11     .cui-tab-mod li.cui-tab-current { color: #099fde; }
12     .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease ; transition: transform 300ms ease ; z-index: -1; -webkit-backface-visibility:hidden; backface-visibility:hidden;     }
13     .cui-tabnum2 { width: 50%; }
14     .cui-tabnum3 { width: 33.33333%; }
15     .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
16   </style>
17   <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
18 </head>
19 <body>
20   <ul class="cui-tab-mod">
21     <li data-key="0" data-index="0" class="cui-item cui-tab-current">中國</li>
22     <li data-key="1" data-index="1" class="cui-item">美國</li>
23     <li data-key="2" data-index="2" class="cui-item">日本</li>
24     <i class="cui-tab-scrollbar cui-tabnum3"><span>1</span></i>
25   </ul>
26   <script type="text/javascript">
27     var wrapper = $('.cui-tab-mod');
28     var toolBar = $('.cui-tab-scrollbar');
29     var els = wrapper.find('li');
30     wrapper.on('click', function (e) {
31       toolBar.css({
32         '-webkit-transform': 'translate3d(100%,0,0)',
33         'transform': 'translate3d(100%,0,0)'
34       })
35       var el = $(e.target);
36     });
37   </script>
38 </body>
39 </html>

若是這樣,我直接操做toolBar即可以繞過該BUG,可是我仍是不太肯定,因此有了這段代碼:

 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4   <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
 5   <title></title>
 6   <style type="text/css">
 7     body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
 8     
 9     ul, ol { list-style: none; margin: 0; padding: 0; }
10     
11     .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
12     
13     .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
14     
15     .cui-tab-mod li.cui-tab-current { color: #099fde; }
16     
17     .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease ; transition: transform 300ms ease ; z-index: -1; -webkit-backface-visibility:hidden; backface-visibility:hidden;     }
18     
19     .cui-tabnum2 { width: 50%; }
20     
21     .cui-tabnum3 { width: 33.33333%; }
22     
23     .cui-tabnum4 { width: 25%; }
24     
25     .cui-tabnum5 { width: 20%; }
26     
27     .cui-tabnum6 { width: 16.66666%; }
28     
29     .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
30     
31     .cui-tab-mod cui-tab-current  .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); }
32     
33     
34     .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }
35     
36     .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); }
37     
38     .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); }
39 
40   </style>
41   <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
42 </head>
43 <body>
44 
45   <ul class="cui-tab-mod">
46     <li data-key="0" data-index="0" class="cui-item cui-tab-current">中國</li>
47     <li data-key="1" data-index="1" class="cui-item">美國</li>
48     <li data-key="2" data-index="2" class="cui-item">日本</li>
49     <i class="cui-tab-scrollbar cui-tabnum3"><span>1</span></i>
50   </ul>
51   <script type="text/javascript">
52     var wrapper = $('.cui-tab-mod');
53     var toolBar = $('.cui-tab-scrollbar');
54     var els = wrapper.find('li');
55 
56     wrapper.on('click', function (e) {
57       var el = $(e.target);
58       els.removeClass('cui-tab-current');
59       el.addClass('cui-tab-current');
60       toolBar.css('left', '0');
61 
62       //      setTimeout(function () {
63       //        toolBar.width('width', toolBar.width());
64       //      }, 0)
65     });
66 
67 
68  
69   </script>
70 </body>
71 </html>
View Code
 1 var wrapper = $('.cui-tab-mod');
 2 var toolBar = $('.cui-tab-scrollbar');
 3 var els = wrapper.find('li');
 4 
 5 wrapper.on('click', function (e) {
 6   var el = $(e.target);
 7   els.removeClass('cui-tab-current');
 8   el.addClass('cui-tab-current');
 9   toolBar.css('left', '0');
10 
11   //      setTimeout(function () {
12   //        toolBar.width('width', toolBar.width());
13   //      }, 0)
14 });

 

 

 

 

 

 

 

 

 

這一段代碼也能夠解決BUG,彷佛解決bug的元素是致使了absolute元素的迴流而與其它無關,這裏再次對比Timeline:

兩次對比沒有什麼差距,這個BUG致使的緣由還須要深究,待我哪天去真機測試...... 

setTimeout動畫

另外,最好也不要使用setTimeout之類的定時器來實現動畫,下面這個動畫操做也是很是消耗的:

這裏若是使用requestAnimationFrame即可以免Timer的影響。

fixed元素

通常來講,fixed元素在手機上尤爲卡,咱們這裏也來追蹤一下緣由:

能夠看到,fixed元素與left同樣的都會不斷的Paint,因此他卡呢,至於如何避免不一樣的團隊有不一樣的方案。

結語

今天回顧了與宇果的交流過程當中的渲染優化相關,這裏還停留在比較淺的層次,須要繼續學習,但願對各位有用,文中有誤請您提出,最後微博求粉:

相關文章
相關標籤/搜索