[英]ExtJs best practices
似乎大多數ExtJS書籍和ExtJS介紹只關注顯示所有不錯的功能,但大多數並沒有真正解釋如何使用ExtJS構建穩定,可維護的布局/應用程序。 如何寫它們而不會造成難以理解的混亂......
我沒有特定的應用程序,我只是想知道如何“美化”我的ExtJS代碼。 因此,如果您需要一個示例,項目管理(庫)或類似工作板的“常規”應用程序將最好地描述我的想法。
因此,當我想使用ExtJS為客戶端代碼構建這些應用程序時,任何人都可以分享一些關於如何構建這些應用程序的良好鏈接或建議嗎?
提前謝謝,干杯
在我的公司主要代碼審查員執行:
作為遵循文檔的幾個主要規則...... :)
關於十大最差實踐的Sencha博客文章值得一讀。
博客文章摘要
**請注意,所有信用均歸原始博文的合法所有者所有。
1.組件結構的過度或不必要的嵌套
有時開發人員使用冗余嵌套組件,這可能會在應用程序中產生意外的不吸引人的美感,例如雙邊框或意外的布局行為。
壞
items: [{
xtype : 'panel',
title: ‘My Cool Grid’,
layout: ‘fit’,
items : [{
xtype : 'grid',
store : 'MyStore',
columns : [{...}]
}]
}]
好
layout: ‘fit’,
items: [{
xtype : 'grid',
title: ‘My Cool Grid’,
store : 'MyStore',
columns : [{...}]
}]
在上面的示例中,嵌套面板是冗余的,因為grid是面板的擴展。 此外,其他元素如形狀,樹木,標簽面板是面板的延伸。
2.由於未清除未使用的組件而導致的內存泄漏。
這是有史以來最重要的規則之一。 在任何編程語言中,確保不再使用的組件被正確丟棄是非常非常重要的,即使在Java這樣的語言中,GC正在為我們進行所有清理工作,我們應該確保我們不會持有任何編程語言。我們完成它們之后的對象。
壞
Ext.define('MyApp.view.MyGrid',{
extend : 'Ext.grid.Panel',
columns : [{...}],
store: ‘MyStore’,
initComponent : function(){
this.callParent(arguments);
this.on({
scope : this,
itemcontextmenu : this.onItemContextMenu
});
},
onItemContextMenu : function(view,rec,item,index,event){
event.stopEvent();
Ext.create('Ext.menu.Menu',{
items : [{
text : 'Do Something'
}]
}).showAt(event.getXY());
}
});
每次用戶右鍵單擊網格行時,都會創建一個新的上下文菜單。 哪個看起來不錯,因為我們只看到最新的菜單。
壞(??)
Ext.define('MyApp.view.MyGrid',{
extend : 'Ext.grid.Panel',
store : 'MyStore',
columns : [{...}],
initComponent : function(){
this.menu = this.buildMenu();
this.callParent(arguments);
this.on({
scope : this,
itemcontextmenu : this.onItemContextMenu
});
},
buildMenu : function(){
return Ext.create('Ext.menu.Menu',{
items : [{
text : 'Do Something'
}]
});
},
onItemContextMenu : function(view,rec,item,index,event){
event.stopEvent();
this.menu.showAt(event.getXY());
}
});
這比初始的要好一些。 每當用戶右鍵單擊網格視圖時,它就會使用相同的菜單對象。 但是,即使我們殺死網格視圖,它也會使菜單保持活動狀態,這不是我們需要的。
好
Ext.define('MyApp.view.MyGrid',{
extend : 'Ext.grid.Panel',
store : 'MyStore',
columns : [{...}],
initComponent : function(){
this.menu = this.buildMenu();
this.callParent(arguments);
this.on({
scope : this,
itemcontextmenu : this.onItemContextMenu
});
},
buildMenu : function(){
return Ext.create('Ext.menu.Menu',{
items : [{
text : 'Do Something'
}]
});
},
onDestroy : function(){
this.menu.destroy();
this.callParent(arguments);
},
onItemContextMenu : function(view,rec,item,index,event){
event.stopEvent();
this.menu.showAt(event.getXY());
}
});
在上面的視圖中,當網格被銷毀時,我們也會破壞菜單。
3.怪物控制器
有些人像怪物一樣編碼......開玩笑,但是有一些大型控制器(不只是控制器,其他組件也是如此:))由數千行代碼組成,完成所有那些根本沒有關系的東西。
在項目開始時找到一種將應用程序分解為不同處理單元的方法非常重要,這樣您就不會得到一個處理應用程序中所有進程的巨型控制器。
建議:
通過不同的方式分解你的申請
APP功能(在訂單處理應用程序中 - >訂購,交付,客戶查找等)
視圖(網格,表格等)
在ExtJS中,控制器可以相互通信。
this.getController('SomeOtherController').runSomeFunction(myParm);
也可以觸發任何控制器可以偵聽的應用程序級事件。
MyApp.getApplication().fireEvent('myevent');
另一個控制器監聽app級事件。
MyApp.getApplication().on({
myevent : doSomething
});
4.源代碼的文件夾結構不佳
在任何應用程序中,良好的結構都非常重要,因為它提高了項目的可讀性和可維護性。 不是將所有控制器放在一個文件夾中,而是將所有視圖放在另一個文件夾中,最好根據它們的功能邏輯地構造它們。
5.使用全局變量
為什么使用全局變量是不好的? 有時它不清楚它所擁有的實際價值,因此它可能導致許多混淆,如
很難在運行時發現很難調試的bug
我們對於它可以做些什么呢? 我們可以為它們定義一個單獨的類並將它們存儲在其中。
5.1首先,我們創建一個單獨的javascript文件,其中包含在使用應用程序時需要更改的變量。
Runtime.js
5.2定義一個類來保存全局可用數據,在本例中為“myLastCustomer”變量
Ext.define('MyApp.config.Runtime',{ singleton : true, config : { myLastCustomer : 0 // initialize to 0 }, constructor : function(config){ this.initConfig(config); } });
5.3然后在整個申請過程中提供可用的變量
Ext.application({ name : 'MyApp', requires : ['MyApp.config.Runtime'], ... });
5.4每當你想獲取或設置全局變量值時
5.4.1設置值
MyApp.config.setMyLastCustomer(12345);
5.4.2獲取價值
MyApp.config.getMyLastCustomer();
6.在組件中使用id是個壞主意?
為什么?
6.1因為您定義的每個id都應該是唯一的。 在大型應用程序中,這可能會導致許多混淆和問題。
6.2很容易讓框架處理組件的命名
// here we define the first save button
xtype : 'toolbar',
items : [{
text : ‘Save Picture’,
id : 'savebutton'
}]
// somewhere else in the code we have another component with an id of ‘savebutton’
xtype : 'toolbar',
items : [{
text : ‘Save Order’,
id : 'savebutton'
}]
在上面的示例中,有兩個具有相同名稱的按鈕,這會導致名稱沖突。 要防止它,請使用“itemId”而不是id。
xtype : 'toolbar',
itemId : ‘picturetoolbar’,
items : [{
text : 'Save Picture',
itemId : 'savebutton'
}]
// somewhere else in the code we have another component with an itemId of ‘savebutton’
xtype : 'toolbar',
itemId: ‘ordertoolbar’,
items : [{
text : ‘Save Order’,
itemId: ‘savebutton’
}]
現在,您可以按照下面的唯一名稱訪問上述組件
var pictureSaveButton = Ext.ComponentQuery.query('#picturetoolbar > #savebutton')[0];
var orderSaveButton = Ext.ComponentQuery.query('#ordertoolbar > #savebutton')[0];
// assuming we have a reference to the “picturetoolbar” as picToolbar
picToolbar.down(‘#savebutton’);
7.組件的不可靠引用
使用組件定位來獲取對組件的引用不是一個好主意。 因為某人可能會更改組件的位置而不知道它是通過定位在應用程序的另一部分中而引用的。
var mySaveButton = myToolbar.items.getAt(2);
var myWindow = myToolbar.ownerCt;
我們如何獲得參考? 使用“ComponentQuery”或“up”/“down”方法。
var pictureSaveButton = Ext.ComponentQuery.query('#picturetoolbar > #savebutton')[0]; // Quering against the itemId
var mySaveButton = myToolbar.down(‘#savebutton’); // searching against itemId
var myWindow = myToolbar.up(‘window’);
8.願意遵循大/小寫命名慣例
使用良好的命名約定作為最佳實踐非常重要,因為它可以提高代碼的一致性並使其易於閱讀和理解。 同樣重要的是為您定義的所有類,變量和方法使用有意義的名稱。
壞
Ext.define(‘MyApp.view.customerlist’,{ // should be capitalized and then camelCase
extend : ‘Ext.grid.Panel’,
alias : ‘widget.Customerlist’, // should be lowercase
MyCustomConfig : ‘xyz’, // should be camelCase
initComponent : function(){
Ext.apply(this,{
store : ‘Customers’,
….
});
this.callParent(arguments);
}
});
好
Ext.define(‘MyApp.view.CustomerList’,{ // Use of capitalized and then camelCase
extend : ‘Ext.grid.Panel’,
alias : ‘widget.customerlist’, // use of lowerCase
myCustomConfig : ‘xyz’, // Use of camelCase
initComponent : function(){
Ext.apply(this,{
store : ‘Customers’,
….
});
this.callParent(arguments);
}
});
9.將組件約束到父組件布局。
壞
Ext.define('MyApp.view.MyGrid',{
extend : 'Ext.grid.Panel',
initComponent : function(){
Ext.apply(this,{
store : ‘MyStore’,
region : 'center',
......
});
this.callParent(arguments);
}
});
“MyGrid”面板布局區域設置為“中心”。 因此它不能在“西方”等其他地區重復使用。 因此,重要的是以一種可以在任何問題中重復使用的方式定義您的組件。
壞(??)
Ext.define('MyApp.view.MyGrid',{
extend : 'Ext.grid.Panel',
initComponent : function(){
Ext.apply(this,{
store : ‘MyStore’,
......
});
}
});
Ext.create('MyApp.view.MyGrid',{
region : 'center' // specify the region when the component is created.
});
還有另一種方法可以定義具有默認值的組件(在本例中為“region”屬性),並在默認值需要更改時覆蓋默認值。
好
Ext.define('MyApp.view.MyGrid',{
extend : 'Ext.grid.Panel',
region : 'center', // default region
initComponent : function(){
Ext.apply(this,{
store : ‘MyStore’,
......
});
}
});
Ext.create(‘MyApp.view.MyGrid’,{
region : ‘north’, // overridden region
height : 400
});
10.使代碼更加復雜。
有許多方法可以使簡單的代碼變得復雜。 許多方法之一是通過單獨訪問表單中的每個字段來加載表單數據。
壞
// suppose the following fields exist within a form
items : [{
fieldLabel : ‘User’,
itemId : ‘username’
},{
fieldLabel : ‘Email’,
itemId : ‘email’
},{
fieldLabel : ‘Home Address’,
itemId : ‘address’
}];
// you could load the values from a record into each form field individually
myForm.down(‘#username’).setValue(record.get(‘UserName’));
myForm.down(‘#email’).setValue(record.get(‘Email’));
myForm.down(‘#address’).setValue(record.get(‘Address’));
好
items : [{
fieldLabel : ‘User’,
name : ‘UserName’
},{
fieldLabel : ‘Email’,
name : ‘Email’
},{
fieldLabel : ‘Home Address’,
name : ‘Address’
}];
myForm.loadRecord(record); // use of "loadRecord" to load the entire form at once.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.