小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

10個(gè)應(yīng)該避免的ExtJS開(kāi)發(fā)實(shí)踐

 dengshisong 2017-02-14

1、過(guò)度或不必要的組件嵌套

開(kāi)發(fā)人員最常犯的錯(cuò)誤之一就是沒(méi)有理由的組件嵌套。這會(huì)損耗性能并且導(dǎo)致不夠美觀,比如雙邊框或布局異常等。在下面的例子中,有一個(gè)僅僅包含Grid的Panel,在這種情況下,Panel是不必要的。記住像Form、Tree、TabPanel和Grid都繼承自Panel,因此在使用這些組件時(shí),應(yīng)特別注意不必要的組件嵌套情況。

  1. items: [{  
  2.     xtype : 'panel',  
  3.     title: ‘My Cool Grid’,  
  4.     layout: ‘fit’,  
  5.     items : [{  
  6.         xtype : 'grid',  
  7.         store : 'MyStore',  
  8.         columns : [{...}]  
  9.     }]  
  10. }]  
BAD:這里的Panel是不必要的。
  1. layout: ‘fit’,  
  2. items: [{  
  3.     xtype : 'grid',  
  4.     title: ‘My Cool Grid’,  
  5.     store : 'MyStore',  
  6.     columns : [{...}]  
  7. }]  
Good:Grid是Panel的子類,因此可以直接在Grid上使用Panel的屬性。


2、未清除沒(méi)有使用的組件導(dǎo)致內(nèi)存泄露

許多開(kāi)發(fā)者都想知道,為什么應(yīng)用使用的時(shí)間越長(zhǎng),響應(yīng)速度就越慢。在應(yīng)用中未清除沒(méi)有使用的的組件是最大的原因。在下面的例子中,每次用戶在Grid的行上點(diǎn)擊右鍵菜單,一個(gè)新的Menu實(shí)例便會(huì)被創(chuàng)建。如果用戶一直使用應(yīng)用并右鍵點(diǎn)擊了Grid行幾百次,那便會(huì)有幾百個(gè)Menu實(shí)例存在,并且永遠(yuǎn)不會(huì)被銷毀。對(duì)開(kāi)發(fā)者和用戶來(lái)說(shuō),應(yīng)用表面上看起來(lái)是正確的,因?yàn)橹挥凶詈髣?chuàng)建的Menu實(shí)例才會(huì)顯示在頁(yè)面上,其余的全都被隱藏了。隨著新的Menu實(shí)例被創(chuàng)建而老的又沒(méi)有被銷毀,應(yīng)用消耗的內(nèi)存會(huì)持續(xù)保持增長(zhǎng)。這最終會(huì)導(dǎo)致操作變得越來(lái)越慢甚至瀏覽器崩潰。

在初始化Grid的時(shí)候,只創(chuàng)建Menu實(shí)例一次并在每次用戶右鍵點(diǎn)擊時(shí)進(jìn)行復(fù)用,是比較好的一種改善方式。即便如此,當(dāng)Grid被銷毀時(shí),上下文菜單雖然已經(jīng)不需要了,但卻依然存在。最好的方式是在Grid被銷毀時(shí),上下文菜單也隨之進(jìn)行銷毀。

  1. Ext.define('MyApp.view.MyGrid',{  
  2.     extend : 'Ext.grid.Panel',  
  3.     columns : [{...}],  
  4.     store: ‘MyStore’,  
  5.     initComponent : function(){  
  6.         this.callParent(arguments);  
  7.         this.on({  
  8.             scope : this,  
  9.             itemcontextmenu : this.onItemContextMenu  
  10.         });  
  11.     },  
  12.   
  13.     onItemContextMenu : function(view,rec,item,index,event){  
  14.         event.stopEvent();  
  15.         Ext.create('Ext.menu.Menu',{  
  16.             items : [{  
  17.                 text : 'Do Something'  
  18.             }]  
  19.         }).showAt(event.getXY());  
  20.   
  21.     }  
  22. });  
BAD:在每次右鍵點(diǎn)擊時(shí)都會(huì)創(chuàng)建一個(gè)Menu實(shí)例,并且永遠(yuǎn)不會(huì)被銷毀。
  1. Ext.define('MyApp.view.MyGrid',{  
  2.     extend : 'Ext.grid.Panel',  
  3.     store : 'MyStore',  
  4.     columns : [{...}],  
  5.     initComponent : function(){  
  6.         this.menu = this.buildMenu();  
  7.         this.callParent(arguments);  
  8.         this.on({  
  9.             scope : this,  
  10.             itemcontextmenu : this.onItemContextMenu,  
  11.                    destroy: this.onDestroy  
  12.         });  
  13.     },  
  14.   
  15.     buildMenu : function(){  
  16.         return Ext.create('Ext.menu.Menu',{  
  17.             items : [{  
  18.                 text : 'Do Something'  
  19.             }]  
  20.         });  
  21.     },  
  22.   
  23.     onDestroy : function(){  
  24.         this.menu.destroy();  
  25.         this.callParent(arguments);  
  26.     },  
  27.   
  28.     onItemContextMenu : function(view,rec,item,index,event){  
  29.         event.stopEvent();  
  30.         this.menu.showAt(event.getXY());  
  31.     }  
  32. });  
Better:當(dāng)Grid被銷毀的時(shí)候,上下文菜單也隨之進(jìn)行銷毀。

3、巨大的控制器

這是令人驚奇的,我們看到的應(yīng)用常常會(huì)有一個(gè)由數(shù)千行代碼組成的巨大控制器。我們傾向于根據(jù)應(yīng)用程序的功能來(lái)拆分我們的控制器,它使導(dǎo)航和維護(hù)代碼更容易。很多開(kāi)發(fā)者喜歡通過(guò)視圖來(lái)拆分控制器。例如,如果一個(gè)應(yīng)用有一個(gè)Grid和一個(gè)Form,那么將分別有一個(gè)管理Grid和管理From的控制器。只要你能始終保持一致,就沒(méi)有一種絕對(duì)正確的方式來(lái)分離控制器邏輯。另外,控制器可以和另外控制器產(chǎn)生聯(lián)系。下面的代碼將演示如何檢索其他的控制器并調(diào)用其方法。

  1. this.getController('SomeOtherController').runSomeFunction(myParm);  
你可以觸發(fā)一個(gè)應(yīng)用級(jí)別的事件,并且任何控制器都可以進(jìn)行監(jiān)聽(tīng)。下面的代碼將演示如何在一個(gè)控制器中觸發(fā)應(yīng)用級(jí)別的事件,并在另一個(gè)控制器中對(duì)該事件進(jìn)行監(jiān)聽(tīng)。
  1. MyApp.getApplication().fireEvent('myevent');  
觸發(fā)應(yīng)用級(jí)別事件
  1. MyApp.getApplication().on({  
  2.     myevent : doSomething  
  3. });  
在另一個(gè)控制器中進(jìn)行監(jiān)聽(tīng)

4、源碼的文件組織較差

這并不會(huì)影響應(yīng)用性能和操作,但卻讓人很難理清應(yīng)用的文件組織結(jié)構(gòu)。隨著應(yīng)用規(guī)模的擴(kuò)大,如果你能很好地組織你的源碼,那么在代碼中迅速定位并添加新的特性和方法將變得比較容易。就像下圖所示,很多開(kāi)發(fā)者會(huì)把所有的視圖文件(甚至整個(gè)項(xiàng)目)都放在同一個(gè)文件夾下。

我們推薦根據(jù)業(yè)務(wù)邏輯對(duì)視圖文件進(jìn)行組織分類:

 
 5、使用全局變量

雖然使用全局變量的壞處眾所周知,但我們還是在最近審查的很多項(xiàng)目中看到。使用全局變量的應(yīng)用存在命名沖突、難以調(diào)試等重大問(wèn)題。相比使用全局變量,更好的做法是使用類的“properies”,并通過(guò)getters和setters來(lái)引用這些屬性。例如,為了讓你的應(yīng)用記住最后被選擇的客戶,你可能會(huì)像下面的代碼一樣臨時(shí)定義一個(gè)變量,這很簡(jiǎn)單并且它的值在應(yīng)用的所有部分都是有效的。

  1. myLastCustomer = 123456;  

BAD:使用全局變量來(lái)存儲(chǔ)客戶編號(hào)。

更好的實(shí)現(xiàn)方式是創(chuàng)建一個(gè)類,它持有的屬性可以在全局范圍內(nèi)使用。在這種情況下,我們可以創(chuàng)建一個(gè)名為Runtime.js的文件來(lái)保存運(yùn)行時(shí)屬性。我們可以把該文件放在config文件夾下:

 
 Runtime.js文件內(nèi)容:
  1. Ext.define(‘MyApp.config.Runtime’,{  
  2.     singleton : true,  
  3.     config : {  
  4.         myLastCustomer : 0   // initialize to 0  
  5.     },  
  6.     constructor : function(config){  
  7.         this.initConfig(config);  
  8.     }  
  9. });  
在應(yīng)用中引用Runtime.js
  1. Ext.application({  
  2.     name : ‘MyApp’,  
  3.     requires : [‘MyApp.config.Runtime’],  
  4.    ...  
  5. });  
Set屬性的值
  1. MyApp.config.setMyLastCustomer(12345);  
Get屬性的值
MyApp.config.getMyLastCustomer(); 

6、使用"id"

因?yàn)槊恳粋€(gè)id都必須是唯一的,所以我們不推薦在組件上使用id。在項(xiàng)目中很容易多次使用相同的id,這將導(dǎo)致重復(fù)id的DOM(命名沖突)。相反,應(yīng)該讓框架來(lái)為你處理生成id的問(wèn)題。有了ComponentQuery,就無(wú)需為組件定義一個(gè)id。下面的代碼演示了在一個(gè)應(yīng)用中存在兩個(gè)不同的保存按鈕,它們卻有相同的id,這將導(dǎo)致命名沖突。雖然在下面的代碼中很容易發(fā)現(xiàn)問(wèn)題,但在一個(gè)龐大的實(shí)際項(xiàng)目中卻很難。

  1. // here we define the first save button  
  2. xtype : 'toolbar',  
  3. items : [{  
  4.     text : ‘Save Picture’,  
  5.     id : 'savebutton'  
  6. }]  
  7.   
  8. // somewhere else in the code we have another component with an id of ‘savebutton’  
  9. xtype : 'toolbar',  
  10. items : [{  
  11.     text : ‘Save Order’,  
  12.     id : 'savebutton'  
  13. }]  

BAD:給不同組件定義重復(fù)的id將導(dǎo)致命名沖突。

如果你想手動(dòng)識(shí)別每個(gè)不同的組件,可以像下面的例子中使用itemId來(lái)代替id。這將解決命名沖突的問(wèn)題,并且仍然可以通過(guò)itemId來(lái)獲得對(duì)組件的引用。

  1. xtype : 'toolbar',  
  2. itemId : ‘picturetoolbar’,  
  3. items : [{  
  4.     text : 'Save Picture',  
  5.     itemId : 'savebutton'  
  6. }]  
  7.   
  8. // somewhere else in the code we have another component with an itemId of ‘savebutton’  
  9. xtype : 'toolbar',  
  10. itemId: ‘ordertoolbar’,  
  11. items : [{  
  12.     text : ‘Save Order’,  
  13.     itemId: ‘savebutton’  
  14. }]  

有很多種方式可以通過(guò)itemId來(lái)獲得對(duì)組件的引用,如下面的代碼所示:

  1. var pictureSaveButton = Ext.ComponentQuery.query('#picturetoolbar > #savebutton')[0];  
  2.   
  3. var orderSaveButton = Ext.ComponentQuery.query('#ordertoolbar > #savebutton')[0];   
  4.   
  5. // assuming we have a reference to the “picturetoolbar” as picToolbar  
  6. picToolbar.down(‘#savebutton’); 

7、對(duì)組件不可靠的引用

我們時(shí)??吹揭恍┐a,通過(guò)組件定位來(lái)獲得對(duì)它的引用。如果有任何元素被添加、刪除或嵌套在不同的組件里,這樣的代碼將很容易被破壞。下面的代碼展示了常見(jiàn)的兩種情況:

  1. var mySaveButton = myToolbar.items.getAt(2);  
  2.   
  3. var myWindow = myToolbar.ownerCt; 

BAD:避免通過(guò)組件定位來(lái)獲得對(duì)它的引用。

相反,應(yīng)該像下面的代碼中通過(guò)ComponentQuery或組件的up/down方法來(lái)獲得對(duì)組件的引用。通過(guò)這種方式,代碼將不太容易被破壞,即使組件的結(jié)構(gòu)或順序發(fā)生了改變。

  1. var mySaveButton = myToolbar.down(‘#savebutton’);    // searching against itemId  
  2.   
  3. var myWindow = myToolbar.up(‘window’); 
GOOD:通過(guò)ComponentQuery來(lái)獲得對(duì)組件的引用。
8、沒(méi)有遵從有關(guān)大小寫的命名約定

Ext在命名class、component、properties、xtype等時(shí),遵從特定的大小寫規(guī)范。為了避免混淆和代碼清晰,應(yīng)該始終遵從一致的命名規(guī)范。

  1. xt.define(‘MyApp.view.customerlist’,{          // should be capitalized and then camelCase  
  2.     extend : ‘Ext.grid.Panel’,  
  3.     alias : ‘widget.Customerlist’,                       // should be lowercase               
  4.     MyCustomConfig : ‘xyz’,                            // should be camelCase  
  5.     initComponent : function(){  
  6.         Ext.apply(this,{  
  7.             store : ‘Customers’,  
  8.             ….  
  9.         });  
  10.         this.callParent(arguments);  
  11.     }  
  12. });  
BAD:與Ext不一致的命名約定。
  1. Ext.define(‘MyApp.view.CustomerList’,{        
  2.     extend : ‘Ext.grid.Panel’,  
  3.     alias : ‘widget.customerlist’,        
  4.     myCustomConfig : ‘xyz’,              
  5.     initComponent : function(){  
  6.         Ext.apply(this,{  
  7.             store : ‘Customers’,  
  8.             ….  
  9.         });  
  10.         this.callParent(arguments);  
  11.     }  
  12. });  
GOOD:保持與Ext一致的命名規(guī)范。

此外,如果你想要觸發(fā)自定義事件,那事件的名稱應(yīng)該全小寫。當(dāng)然,即使你不遵從這些規(guī)范,原有的功能仍然可以正常運(yùn)行,但是為什么要脫離標(biāo)準(zhǔn)并去寫那些不夠清晰的代碼嗎?


9、限定組件在其父組件中的布局

在下面的代碼示例中,面板將總是擁有"region:center"屬性,因此你將不能在其他布局方位中復(fù)用它。

  1. Ext.define('MyApp.view.MyGrid',{  
  2.     extend : 'Ext.grid.Panel',  
  3.     initComponent : function(){  
  4.         Ext.apply(this,{  
  5.             store : ‘MyStore’,  
  6.             region : 'center',  
  7.             ......  
  8.         });  
  9.         this.callParent(arguments);  
  10.     }  
  11. });  
BAD:region屬性不應(yīng)該在這個(gè)地方定義。

下面的例子則展示在實(shí)例化組件并進(jìn)行顯示的時(shí)候才定義布局屬性,通過(guò)這種方式你可以在任何地方復(fù)用該組件并且不會(huì)被布局屬性限制。

  1. Ext.define('MyApp.view.MyGrid',{  
  2.     extend : 'Ext.grid.Panel',  
  3.     initComponent : function(){  
  4.         Ext.apply(this,{  
  5.             store : ‘MyStore’,  
  6.             ......  
  7.         });  
  8.     }  
  9. });  
  10.   
  11. // specify the region when the component is created...  
  12. Ext.create('MyApp.view.MyGrid',{  
  13.     region : 'center'   
  14. });  
GOOD:在創(chuàng)建組件實(shí)例的時(shí)候定義布局屬性region。

當(dāng)然,你也可以給組件提供一個(gè)默認(rèn)的布局屬性,然后在必要的時(shí)候進(jìn)行重寫。

  1. Ext.define('MyApp.view.MyGrid',{  
  2.     extend : 'Ext.grid.Panel',  
  3.     region : 'center'// default region  
  4.     initComponent : function(){  
  5.         Ext.apply(this,{  
  6.             store : ‘MyStore’,  
  7.             ......  
  8.         });  
  9.     }  
  10. });  
  11.   
  12. Ext.create(‘MyApp.view.MyGrid’,{  
  13.     region : ‘north’, // overridden region  
  14.     height : 400  
  15. });  
GOOD:定義默認(rèn)的布局屬性,然后在需要的時(shí)候進(jìn)行重寫。

10、復(fù)雜化自己的代碼

很多次我們看到的代碼都比實(shí)際需要的要復(fù)雜,這通常是不完全熟悉每個(gè)組件的可用方法的結(jié)果。最常見(jiàn)到的一種情況就是從數(shù)據(jù)記錄中分別去加載每一個(gè)表單字段。

  1. //  suppose the following fields exist within a form  
  2. items : [{  
  3.     fieldLabel : ‘User’,  
  4.     itemId : ‘username’  
  5. },{  
  6.     fieldLabel : ‘Email’,  
  7.     itemId : ‘email’  
  8. },{  
  9.     fieldLabel : ‘Home Address’,  
  10.     itemId : ‘a(chǎn)ddress’  
  11. }];  
  12.   
  13. // you could load the values from a record into each form field individually  
  14. myForm.down(‘#username’).setValue(record.get(‘UserName’));  
  15. myForm.down(‘#email’).setValue(record.get(‘Email’));  
  16. myForm.down(‘#address’).setValue(record.get(‘Address’));  
BAD:從數(shù)據(jù)記錄中分別加載每一個(gè)表單字段。

其實(shí),可以使用loadRecord方法從數(shù)據(jù)記錄中一次性加載所有的表單字段,關(guān)鍵是表單字段的name屬性和數(shù)據(jù)記錄字段的name要保持一致。

  1. items : [{  
  2.     fieldLabel : ‘User’,  
  3.     name : ‘UserName’  
  4. },{  
  5.     fieldLabel : ‘Email’,  
  6.     name : ‘Email’  
  7. },{  
  8.     fieldLabel : ‘Home Address’,  
  9.     name : ‘Address’  
  10. }];  
  11.   
  12. myForm.loadRecord(record);  
GOOD:使用loadRecord方法在一行代碼中加載所有的表單字段。

以上只是眾多代碼復(fù)雜化的一個(gè)例子,解決這個(gè)問(wèn)題的要點(diǎn)是要瀏覽所有的組件方法和實(shí)例,已確保自己正在使用簡(jiǎn)單、合適的技術(shù)。


原文鏈接:https://www./blog/top-10-ext-js-development-practices-to-avoid-2/


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多