Стоит прочесть статью в блоге Сенчи о десяти худших практиках.
Топ-10 худших практик Сенчи
Резюме из поста в блоге
** Обратите внимание, что все кредиты принадлежат законным владельцам исходного сообщения в блоге.
1.Чрезмерное или ненужное вложение структур компонентов
Иногда разработчики используют избыточные компоненты вложения, что может привести к неожиданной непривлекательной эстетике в приложении со странностями, такими как двойные границы или неожиданное поведение макета.
BAD
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 : [{...}]
}]
В приведенном выше примере вложенная панель является избыточной, поскольку сетка является продолжением панели.Более того, другие элементы, такие как формы, деревья, панели вкладок, являются продолжением панели.
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.Контроллеры монстров
Некоторые люди кодируют как монстры ... Шучу, но есть некоторые большие контроллеры (не только контроллеры, но и другие компоненты :)), которые состоят из тысяч строк кода, выполняющих всете вещи, которые не имеют никакого отношения друг к другу.
Очень важно найти способ разбить ваше приложение на разные процессорные единицы в начале проекта, чтобы вы не получили в итогегигантский контроллер, который обрабатывает все процессы в вашем приложении.
Предложение:
Разбейте ваше приложение по разным
ФУНКЦИЯМ ПРИЛОЖЕНИЯ (В приложении обработки заказов -> Заказ, Доставка, Поиск клиентов ... и т. Д.)
ПРОСМОТР (сетки, формы и т. Д.)
В контроллерах ExtJS можно общаться друг с другом.
this.getController('SomeOtherController').runSomeFunction(myParm);
Также возможно инициировать событие уровня приложения, которое может прослушивать любой контроллер.
MyApp.getApplication().fireEvent('myevent');
Также другой контроллер прослушивает событие уровня приложения.
MyApp.getApplication().on({
myevent : doSomething
});
4.Плохая структура папок для исходного кода
В любом приложении хорошая структура очень важна, поскольку она улучшает удобочитаемость и удобство сопровождения проекта.Вместо того, чтобы помещать все контроллеры в одну папку и все представления в другую папку, лучше структурировать их логически в соответствии с их функциями.
5.Использование глобальных переменных
Почему плохо использовать глобальные переменные?Иногда неясно фактическое значение, которое оно содержит, поэтому это может привести к путанице, такой как
- Конфликты имен
Трудно найти ошибки во время выполнения, которые трудноdebug
Что мы можем с этим сделать?Мы могли бы определить отдельный класс для них и сохранить их в нем.
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 В значение SET
MyApp.config.setMyLastCustomer(12345);
5.4.2 В значение GET
MyApp.config.getMyLastCustomer();
6.Использование идентификаторов в компонентах - плохая идея?
Почему?
6.1 Потому что каждый определенный вами идентификатор должен быть уникальным.В больших приложениях это может привести к путанице и проблемам.
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» или «вверх» / «вниз».
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.Невыполнение соглашений о присвоении имен в верхнем / нижнем регистре
Важно использовать хорошие соглашения о присвоении имен в качестве наилучшей практики, поскольку это улучшает согласованность кода и облегчает его чтение и понимание.Также важно использовать значимые имена для всех определяемых вами классов, переменных и методов.
BAD
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);
}
});
GOOD
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.Привязка компонента к расположению родительских компонентов.
BAD
Ext.define('MyApp.view.MyGrid',{
extend : 'Ext.grid.Panel',
initComponent : function(){
Ext.apply(this,{
store : ‘MyStore’,
region : 'center',
......
});
this.callParent(arguments);
}
});
Область расположения панели «MyGrid» установлена как «центр».Поэтому его нельзя использовать в другом регионе, например, на «западе».Поэтому важно определить ваши компоненты таким образом, чтобы их можно было повторно использовать с любой проблемой.
BAD (??)
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") и отменяют значения по умолчанию, когда требуется изменение значений по умолчанию.
GOOD
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.