Важно.
Если вы этого еще не сделали, обязательно прочитайте первую часть этой статьи. Без этого будет очень трудно объяснить (или даже невозможно), а для вас понять, что написано в этой части.
Вступление.
Прошел уже практически год, с того момента, как я опубликовал первую часть моей статьи. Я успешно использую концепцию пред настроенных классов, чтобы писать реально большие приложения (~150 .js файлов ~60000 строк кода, не считая серверного кода и .css файлов). Приложение полностью модульное, каждый класс это отдельный файл, словом мой способ доказал что он упрощает разработку, организацию кода и отладку.
К сожалению, не все было хорошо у других, кто использовал мой подход, они сталкивались с различными проблемами и Ext Support Team обрабатывали их проблемы и просьбы о помощи. Все это привело в к тому, что мой подход стали называть «абсолютная мерзость» и было сказано, что «это создает проблемы».
Примечание: Как быстрые автомобили сами по себе не приводят к несчастным случаям, хотя тот кто ездит медленно, часто делает это на быстрых машинах, сам способ не может быть настоящей причиной проблем, а вот его применение может.
В любом случае, есть какая-то нелогичность, что я могу использовать данный подход, а кто-то нет.
Так я стал смотреть глубже в причину ошибок и выделил некоторые из них с которыми пользователи могут столкнуться при разработке. Я также буду писать на тему «делать» или «не делать» и когда надо использовать пред настроенные классы, а когда нет. Я не буду сравнивать мой метод с другими (Метод Фабричных функций, прямой метод, загрузка по требованию и другие), потому что 1) я их не использую и 2) я не хочу превратить эту статью в очередной холивар между пользователями Linux и Windows.
Это в полной мере зависит от вас какой способ вы выберете. Однако, если вы выберете мой способ, то следуйте правилам, которые я хочу изложить.
Наиболее распространенные источники ошибок.
- Бездумный копи-паст
- Расширение класса базирующегося не на Ext.Component
- Не вызываются родительские методы
- initialConfig
- Слушатели событий
Бездумные копи-пастеры.
Вы знаете этих людей ? Они пишут на форуме:
Мне нужно перетащить текст с Tree на Grid, дай pliz полный рабочий codez.
И если кто-то и альтруистов пишет им фрагмент его «codez», чтобы помочь ему, то в ответ будет:
Твой код не работает, помоги мне, мой менеджер хочет чтобы все работало.
Вы ведите, что происходит, такой «разработчик» , получив код на форуме скопипастил его, без задней мысли, не понимая, что этот код вообще делает, может даже он не изменил URL для своего сервера, и конечно же все не работает.
Это конечно крайности (но они случаются не столь редко, как вы могли подумать), тем не менее бездумный копи-паст может перевести лишь к разочарованиям.
Я не против копи-паста в целом, с помощью него можно сэкономить уйму времени, я тоже иногда это делают, но я против бездумного или не правильного понимания и это касается не только программирования, но и реальной жизни.
Правило: Делайте копи-паст, но всегда с пониманием того, что делает код.
Расширение класса основанного не на Ext.Component.
Если класс ExtJS не наследуется от Ext.Component, функция initComponent (Инициализатор компонента), не вызывается, таким образом код, который вы напишете в этой функции никогда не будет выполнен. Вот фрагмент кода из конструктора класса Ext.Component:
this.getId(); Ext.ComponentMgr.register(this); Ext.Component.superclass.constructor.call(this); if(this.baseAction){ this.baseAction.addComponent(this); } this.initComponent();
ExtJS классы которые не наследуются от Ext.Component не имею строчки this.initComponent(); в своем исходном коде.
Правило: Всегда проверяйте, наследуется ли класс, который вы хотите пред настроить, от класса Ext.Component. Вы должны использовать другой подход, если это не так.
Не вызываются родительские методы.
Часто случается так, что вы не только добавляете несколько методов в наследуемый класс, но так же вы изменяете уже существующие методы. initComponent — первый пример, onRender, afterLayout, и другие (но и не только они) часто переопределяемые методы.
Эти методы уже есть в вашем классе и в родительском, от которого вы его наследуете, поэтому, если вы забудете строчки:
// in initComponent override YourExtension.superclass.initComponent.apply(this, arguments); // or in onRender override YourExtension.superclass.onRender.apply(this, arguments); // or in afterLayout override YourExtension.superclass.afterLayout.apply(this, arguments);
ваш класс работать не будет.
Правило: Никогда не забывайте вызвать родительский метод, если вы уверены в том, что вы делаете.
initialConfig.
Конструктор класса Ext.Component сохраняет переданный ему конфиг, как свойство initialConfig:
/** * This Component's initial configuration specification. Read-only. * @type Object * @property initialConfig */ this.initialConfig = config; Ext.apply(this, config); this.addEvents(/* abbreviated for clarity */); this.getId(); Ext.ComponentMgr.register(this); Ext.Component.superclass.constructor.call(this); if(this.baseAction){ this.baseAction.addComponent(this); } this.initComponent();
Вы видите, что происходит ? Конструктор сохраняет initialConfig до того как выполняется метод initComponent. Таким образом весь ваш конфиг написанный в методе initComponent не сохраняется. Я не заметил этого в первой версии моих шаблонов и примеров, главным образом потому, что есть всего лишь несколько классов, которые используются свойство initialConfig и даже в этих классах вызов initComponent не правильным способом, вызывает ошибку крайне редко. Следующие классы используют свойство initialConfig:
- AnchorLayout
- BorderLayout
- Action
- GridPanel
- Tip
- Combo
- Form
Сейчас я обновил все мои примеры, расширения, шаблоны и основной сайт, чтобы включить в него этот «магический» шаблон:
// create config var config = { // put your config here }; // eo config object // apply config Ext.apply(this, Ext.apply(this.initialConfig, config)); // call parent YourExtension.superclass.initComponent.apply(this, arguments);
Правило: Убедитесь, что ваш класс-потомок сохраняет свойство initialConfig.
Слушатели событий.
Если вы попытаетесь установить обработчики событий, через свойства в конфиге, они не будут работать. Почему ? Ответ опять находится в порядке выполнения действий конструктора Ext.Component:
Ext.Component.superclass.constructor.call(this); if(this.baseAction){ this.baseAction.addComponent(this); } this.initComponent();
Как вы видите конструктор вызывает своего родителя, который является классом Ext.util.Observable до initComponent, а Ext.util.Observable конструктор выполняет:
Ext.util.Observable = function(){ if(this.listeners){ this.on(this.listeners); delete this.listeners; } };
Таким образом любые слушатели событий в initComponent игнорируются.
Существует простой способ решить эту проблему. Положите метод конструктора класса в ваш класс потомок:
constructor:function(config) { // parent constructor call pre-processing - configure listeners here config = config || {}; config.listeners = config.listeners || {}; Ext.applyIf(config.listeners, { // add listeners config here }); // call parent constructor AnExtension.superclass.constructor.call(this, config); // parent constructor call post-processing } // eo function constructor
и определяйте слушателей событий в нем.
Правило: Назначайте слушателей событий в методе-конструкторе.
Заключение.
Если вы решите использовать мой способ написания больших приложений на ExtJS, следуйте следующим правилам:
- Применяйте копи-паст всегда с полным пониманием того, что делает код.
- Всегда проверяйте наследуется ли класс который вы хотите пред настроить от Ext.Component. Вы должны использовать другой подход, если это не так.
- Никогда не забывайте вызвать родительский метод, если вы уверены в том, что делаете.
- Убедитесь что ваш класс сохраняет свойство initialConfig.
- Назначайте слушателей событий в методе-конструкторе.
Удачного наследования!
Источник: http://blog.extjs.eu/know-how/writing-a-big-application-in-ext-part-2/
Очень понравились две предыдущие статьи, жаль что третью так и не написали.
Спасибо за наглядное разъяснение важных базовых вещей.
Почему же третья часть тоже есть Написание больших приложений на ExtJS (Часть3)
Тогда спасибо еще больше! 🙂
Знаки препинания вообще знаете что такое?
Отлично знаю, а вы в курсе что в вашем предложении неправильное согласование слов ? Правильно: «Вы знаете, что такое знаки препинания ?» Да и без аргументов, я удалю ваше сообщение как спам.