亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

ExtJS 4.1性能

系統 1990 0

原文: http://www.sencha.com/blog/ext-js-4-1-performance/

在本文,將講述幾個影響Ext JS應用性能的因素。

  • 網絡延時會嚴重影響初始化啟動時間,尤其是Store的加載時間。
  • CSS處理。
  • Javascript的執行。
  • DOM操作。

網絡延時

為了最大限度的減少應用啟動時間,必須牢記的是,任何域對瀏覽器的網絡連接并發數量是有限制。


這意味著,如果從一個域請求許多文件,一旦達到上限,隨后的下載將要排隊,只有當一個連接槽釋放時,他們才會被處理。新的瀏覽器都有較高范圍,但對舊的、慢的瀏覽器進行優化就很重要。


解決辦法是使用Sencha SDK工具將應用所需的腳本文件生成一個單一的串聯的腳本文件。


具體信息可查看 Ext JS 4.0入門

SDK的“create”命令會分析加載到頁面的應用,加載類定義中requires和user屬性引用的所有文件,然后以正確的順序創建一個包含所有所需的類定義的腳本文件。


可在 Ext JS 4.1的文檔 中查閱Sencha類系統的詳細信息。

另外一種減少網絡延時的方法是在Web服務器對Ext JS的頁面及其相關的腳本和樣式文件啟用GZIP壓縮。

CSS處理

CSS選擇是跟隨DOM的父節點指針從右到左匹配的。

這意味著以下的樣式處理過程是,現在文檔中找到匹配的span,然后沿著父節點這條軸去尋找符合兩個指定樣式類名的祖先節點。

  1. .HeaderContainer.navspan

因而,在元素上使用單一的,確定類名的樣式會更高效。

Javascript執行

優化Javascript代碼必須牢記以下幾點:

  • 避免使用舊的或差的Javascript引擎的寫法。
  • 優化經常重復出現的代碼。
  • 優化在渲染或布局時執行的代碼
  • 最好是盡量不要在初始化渲染或布局時執行任何額外的代碼。
  • 將不變的表達式移到循環外面。
  • 使用for循環代替Ext.Array.each。
  • 如果函數中條件內代碼經常被調用,必要時,將條件移到函數外(可參考Ext JS代碼庫對fireEvent的調用)。
  • 在差的Javascript引擎安裝和拆卸調用框架(讓函數調用所需的設備)會很慢。

代碼優化示例

試想一下,一個統計應用為Grid的數據列提供了一些操作,在Grid的列標題菜單中增加菜單項,以便對任何調用列進行所需的操作。


處理程序必須獲得相關的上下文信息及將要進行操作的當前活動的列標題信息:

ExtJS 4.1性能

GitHub 的示例演示了兩種執行這個操作的方式,它可以運行在任何版本的SDK示例目錄下。

以下是第一種用來合計活動列的寫法:

[javascript] view plain copy
  1. function badTotalFn(menuItem){
  2. var r=store.getRange(),
  3. total=0;
  4. Ext.Array.each(r, function (rec){
  5. total+=rec.get(menuItem.up( 'dataIndex' ).dataIndex);
  6. });
  7. }

這里有幾個錯誤做法。首先,使用Ext.each為數組中的每個記錄調用傳遞函數。正如看到的,函數設置會影響性能。其次,menuItem.up('dataIndex')表達式的結果是不變的,它只需要執行一次,可以放到循環之外。

因此,可將代碼優化成以下代碼:

[javascript] view plain copy
  1. function goodTotalFn(menuItem){
  2. var r=store.getRange(),
  3. field=menuItem.up( 'dataIndex' ).dataIndex;
  4. total=0;
  5. for ( var j=0,l=r.length;j<l;j++){
  6. total+=r[j].get(field);
  7. }
  8. }

這可能似乎微不足道的差異,但性能差異顯著。

在下面表格,計算功能迭代了10000次后,提供了一個可衡量的時間:

Browser Bad Good
Chrome 1700ms 10ms
IE9 18000ms 500ms
IE6 Gave up 532ms


正如所看到的,即使沒有迭代,使用第一個方式,IE9都要花費1.8秒去處理操作。

使用頁面分析器去衡量性能

頁面分析器是SDK的一個示例,在example/page-analyzer目錄可找到它。它會在捕捉框架中運行同一個域的頁面,然后捕捉Ext JS示例,以便分析布局性能和任何對象的任何方法的性能。

如果是使用Chrome,需要在它的命令行使用“-enable-benchmarking”命令開啟微秒計時精度。

要分析以上示例的關鍵位置的性能,切換到“性能”標簽,然后在左下角的標簽面板選擇“Accumulators”標簽,并粘貼以下代碼到textarea:

[javascript] view plain copy
  1. {
  2. "Component.up" :{
  3. "Ext.Component" : "up"
  4. },
  5. "CQ.is" :{
  6. "Ext.ComponentQuery" : "!is"
  7. }
  8. }

確保迭代兩個合計計算函數10000次,才能獲得準確的性能狀態。

然后在頁面分析器中加載Grid性能測試示例,使用“Get total in bad way”開始合計,并單擊頁面分析器的右上角“UPdate Stats”。

ExtJS 4.1性能

然后單擊“Reset”清空accumulators,增加“Build”計時器,使用“Get total in good way”進行合計并單擊頁面分析器的“Update Stats”按鈕。

在“性能”標簽的“Grid”子標簽內,會看到下圖所示的兩個運行結果:

ExtJS 4.1性能

從圖中可以看到,不變表單式在循環外調用ComponentQuery方法的次數要少得多。

合并多個布局操作

Ext JS 4會根據內容變化或大小變化自動進行布局。這意味著,當一個按鈕的文本變化,會導致它所在的工具欄重新布局(因為按鈕的高度可能會改變),而工具欄所在的面板也要重新布局(因為工具欄的高度可能改變)。

基于這個原因,在內容或大小發生改變時,將多個布局操作合并在一起顯得非常重要,可以使用以下代碼實現:

[javascript] view plain copy
  1. {
  2. Ext.suspendLayouts();
  3. //batchofupdates
  4. Ext.resumeLayouts( true );
  5. }

參數true的傳遞意味著重新啟用布局,它運行到這點時,會清理任何排隊的布局請求。

減少DOM負擔

通過減少嵌套的容器或組件以實現盡可能少的層數相當重要,這可以避免重復布局運行和DOM回流,因為這些的開銷是很昂貴的。

另外一個要遵循的原則是使用最簡單的容器或布局做必要的工作。

常見的例子是在將一個Grid放到TabPanel的時候再嵌套一個組件。以下就是習以為常的寫法:

[javascript] view plain copy
  1. {
  2. xtype: "tabpanel" ,
  3. items:[{
  4. title: "Results" ,
  5. items:{
  6. xtype: "grid"
  7. ...
  8. }
  9. }]
  10. }

不知道為什么要添加一個普通面板作為標簽面板的子條目,然后再面板內放置Grid,而這樣的嵌套層毫無用處。

而事實上,這破壞了標簽面板的運作,因為沒有為封裝的面板配置布局,從而不能處理它的子組件Grid的大小變化,這意味著它不能自適應標簽面板的大小,并根據標簽面板的高度進行滾動。

正確的寫法是:

[javascript] view plain copy
  1. {
  2. xtype:”tabpanel“,
  3. items:[{
  4. title:”Results“,
  5. xtype:”grid“,
  6. ...
  7. }]
  8. }

為什么這個原則很重要?

保持組件樹(或DOM樹)盡可能的輕量化是相當重要的,其主要原因是在Ext JS 4中,許多組件是帶有子組件的容器并有執行自己的布局管理器,例如,面板標題現在是一個容器類,在它里面可以配置除標題文本和工具按鈕之外的其它的組件。

雖然將標題作為層次化的容器帶來了額外的開銷,但是這讓UI設計更靈活了。

此外,在Ext JS 4中,組件會使用組件布局管理器去管理內部DOM結構的大小和位置,而不象Ext JS 3.x那樣,使用onResize方法去處理。

可視化的組件樹

在遵循以上原則去設計UI的時候,可以把UI想象為樹結構,例如,一個Viewport可以想象為:

ExtJS 4.1性能

為了渲染yield組件樹,它會運作2次。

第一遍,會調用每個組件的beforeRender,然后調用getRenderTree產生可生成HTML標記的DomHelper的配置對象,并將它添加到渲染緩存中。

第一遍之后,一次性將代表整樹的HTML代碼插入到文檔中,這樣,就減少了創建應用結構時的DOM處理。

然后樹再走一遍,調用每個組件onRender方法將組件連接到他們相關的DOM節點。然后調用afterRender完成渲染處理。

在此之后,完整的初始布局就執行完了。

而這就是為什么創建輕量級UI非常重要的原因。

研究一下下面面板的構成:

[javascript] view plain copy
  1. Ext.create( 'Ext.panel.Panel' ,{
  2. width:400,height:200,
  3. icon: '../shared/icons/fam/book.png' ,
  4. title: 'Test' ,
  5. tools:[{
  6. type: 'gear'
  7. },{
  8. type: 'pin'
  9. }],
  10. renderTo:document.body
  11. });

它會導致相當復雜的UI結構:

ExtJS 4.1性能

盡可能避免收縮封裝(shrinkwrapping,根據內容自動調整大小)

盡管Ext JS 4提供了可自動根據內容調整大小的容器(在Ext JS中簡稱為“shrinkwrapping”),但這會加重部分布局的負擔,其次是計算結果會造成瀏覽器的回流,隨后還要使用計算的高度和寬度重新布局。

避免DOM刷新大小,可提高性能。

盡可能避免限制大小(minHeight, maxHeight, minWidth, maxWidth)

如果限制被命中,那么整個布局就要進行重新計算,例如,一個使用flex定義的盒子布局的子組件在收到其計算寬度小于定義的minWidth時,它會被固定為最小寬度,然后整個盒子布局將不得不重新進行計算。

類似的情形是,一個盒子布局使用stretchMax配置項時,所有子組件將切換為固定的垂直尺寸(例如,Hbox布局高度),而布局則會重新計算。

避免在渲染后處理組件的DOM

為了避免DOM回流和重畫,盡量避免在組件渲染后處理其DOM結構。替代辦法是在生成HTML代碼之前,使用提供的鉤子去修改組件的配置。

如果實在是要修改ODM結構,重寫getRenderTree方法是最后的方式。

Grid的性能

表格的大小會影響性能,尤其是列的數量,因而要保持盡可能少的列數。

如果數據集非常大,而且不想在UI中使用分頁工具條,那么就使用俗稱為“無限Grid”的緩沖渲染方式。

要實現這個,只需要在Store中添加以下配置項:

[javascript] view plain copy
  1. buffered: true ,
  2. pageSize:50, //Whateverworksbestgivenyournetwork/DBlatency
  3. autoLoad: true

然后像往常一樣加載和維護它。

它是如何工作的

Grid會計算渲染表格的大小并根據PagingScroller對象的配置項來監控滾動位置。以下是滾動時需要配置的配置項:

  • trailingBufferZone :保持在可視區域上的已渲染記錄數。
  • leadingBufferZone:保持在可視區域下已渲染的記錄數。
  • numFromEdge:在表格刷新之前,表格滾動時與可視區域之間的邊界值。

渲染的表格需要包含足夠的行數來填充視圖的高度,還要加上緩沖期的大小,以及前導緩沖區的大小,再加上(numFromEdge * 2)以便創建滾動溢出。

表格的滾動結果,會被監控,并在表格末尾與視圖之間的行數小于numFromEdge時,使用數據集中的下一塊數據重新渲染表格,然后定位,以便讓行的可視位置不變。

在最好的情況,重新渲染所需的行已經在頁面緩存中,而操作是瞬時的和察覺不到的。

要配置這些值,可在Grid的verticalScroller配置項中配置:

[javascript] view plain copy
  1. {
  2. xtype: 'gridpanel' ,
  3. verticalScroller:{
  4. numFromEdge:5,
  5. trailingBufferZone:10,
  6. leadingBufferZone:20
  7. }
  8. }

這意味著將有40行的溢出數據提供給Grid可視區域實現平滑滾動,而重新渲染將會在表格邊界與可視區域之間少于5行時發生。

保持管道完整

保持頁面緩存為將來的滾動準備數據是Store的工作。Store也有trailingBufferZone和leadingBufferZone。

每當表格請求重新渲染的行時,在返回請求行之后,Store會確保緩存中的數據涵蓋兩個區域所需的數據,如果數據不在緩存,則會向服務器請求數據。

這兩個區域都有相當大的默認值,開發人員可以調小或調大他們保持在管道中的頁數。

緩存失敗

當“瞬移”到數據集不在緩存部分時,會顯示加載遮蔽和延時渲染,因為需要從服務器請求數據,不過,這種情況已經優化過了。

包含顯示區域所需數據的頁面范圍會優先發生請求,當數據一到達就立刻重新渲染。 trailingBufferZone 和leadingBufferZone所需的數據將會在UI所需數據加載后立刻發送請求。


修剪緩存

默認情況下,緩存會計算最大尺寸,除此之外,它還會丟棄最近使用的頁。頁面數量的大小為滾動條的leadingBufferZone加上可視區域大小,再加上trailingBufferZone和Store的purgePageCount配置項。增加purgePageCount意味著一旦一個頁面被訪問,就可以很快的返回它,而不是向服務器發送請求。

如果purgePageCount的值為0,意味著緩存可以不斷增長,而不用修剪,最終可能增長到包含整個數據集。這在數據集不是大得離譜時是一個非常有用的選項。記住,人類無法理解太多的數據,因而在Grid顯示多于千行的數據實際上沒有多大用處,這可能意味著,他們使用了錯誤過濾條件并需要重新查詢。

將整個數據集放在客戶端

如果數據集不是天文數據集,將整個數據集緩存在頁面是可行的。

可以通過SDK示例目錄下的(examples/grid/infinite-scroll-grid-tuner.html)的“Infinite Grid Tuner”示例來測試下其可行性。

如果設置Store的leadingBufferZone為50000,并設置purgePageCount為0,這將產生預期的效果。

leadingBufferZone會讓Store去保持管道完整,50000意味折非常完整。

purgePageCount 為0意味著頁數的增長沒有限制。

因此,當單擊“Reload”,會看到可視區域需要的數據頁會最先被請求,然后渲染。

然后,會看到Store會努力去填滿巨大的leadingBufferZone。很快,整個數據集就被緩存了,然后,在滾動區域任何地方的數據訪問都是即時的。


作者: Nige "Animal" White
Nigel brings more than 20 years experience to his role as a software architect at Sencha. He has been working with rich Internet applications, and dynamic browser updating techniques since before the term "Ajax" was coined. Since the germination of Ext JS he has contributed code, documentation, and design input.

ExtJS 4.1性能


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日韩视频区| 精品久久久久久中文字幕2017 | 99精品国产成人a∨免费看 | 国产精品四虎在线观看免费 | 日韩 在线视频精品 | 久久国产a| 四虎影视永久费观看在线 | 女人18毛片特级一级免费视频 | 日本特级毛片 | 毛片在线播放a | 狠狠狠地啪香蕉 | 久久免费视频在线观看 | a级毛片视频 | 伊人伊狠亚洲综合影院 | 免费黄色毛片视频 | 久久亚洲精品国产亚洲老地址 | 国产精品亚洲一区二区在线观看 | 国产精品亚洲精品久久成人 | 国产性一交一乱一伦一色一情 | 成人私人影院在线观看网址 | 在线观看国产区 | 狠狠操狠狠| 日韩 欧美 中文字幕 不卡 | 极品欧美人体xxxxoo | 欧美日韩亚洲无线码在线观看 | 精品视频一区二区 | 超清波多野结衣精品一区 | 天天操免费视频 | 久久伊人色综合 | 99久久爱re热6在播放 | 精品视频久久久久 | a一级毛片免费播放 | 老潮湿影院免费体验区 | 97se色在在线视频 | 日本中文一二区有码在线观看 | 九月婷婷天天澡天天添天天爽 | 欧美成人性色生活片天天看 | 婷婷四房综合激情五月在线 | 亚洲精品毛片久久久久久久 | 99在线精品视频 | 久久久99精品久久久久久 |