для initComponent () или нет для initComponent ()

Я борюсь при создании приложения в ExtJS 4, и часть этого является путаницей в том, когда настраивать что-то в initComponent (), а когда нет …

Например, в собственном документе Sencha Application Architecture , когда сначала создавалось представление сетки, они определяли встроенное хранилище в методе initComponent (). (См. Раздел «Определение вида»)

Далее вниз, когда они вытеснили хранилище в отдельный class, они перенесли определение вне initComponent (). Есть полезный комментарий, который обращает внимание на этот факт, но объяснений нет. (См. Раздел Создание раздела «Модель и магазин»)

Я предполагаю, что причина должна быть очевидной, но я пропустил ее. Любые указатели?

    Если у вас нет глубокого понимания того, как работает система classа ExtJS, вы можете следовать этому:

    Объявите все непримитивные типы в initComponent() .

    терминология

    • Примитивные типы – строки, булевы, целые числа и т. Д.
    • Непримитивы – массивы и объекты.

    объяснение

    Если компонент, который вы продлеваете, должен создаваться более одного раза, любые не примитивные конфиги, объявленные как опция конфигурации (вне initComponent ), будут совместно использоваться всеми экземплярами.

    Из-за этого многие люди столкнулись с проблемами, когда расширенный компонент (обычно расширенная grid) создается на нескольких вкладках.

    Такое поведение объясняется в ответе sra ниже и в этой статье в журнале Skirtle’s Den . Вы также можете прочитать этот вопрос .

    Сначала я остановлюсь на своих комментариях:

    @ Александр Токарев Не поймите меня неправильно. Я не говорю о конфигурациях компонентов или, что еще хуже, о случаях и перемещении их в initComponent() , это не моя точка.

    Теперь я думаю об этом.

    initComponent () должен разрешить все необходимое время, когда создается экземпляр этого classа. Не больше, не меньше.

    Вы можете испортить нагрузку при определении classов, и большая часть этого происходит, потому что люди не понимают, как работает classная система ExtJS. Поскольку речь идет о компонентах, основное внимание будет уделено этим. Это также будет упрощенный пример, который должен показывать только некоторую ошибку, которую я видел много раз.

    Начнем: у нас есть настраиваемая панель, которая делает много отличных вещей. Это вызывает необходимость в пользовательской конфигурации, мы называем ее foo . Мы добавляем его вместе с нашей опцией конфигурации по умолчанию для определения classа, чтобы мы могли получить к нему доступ:

     Ext.define('Custom', { extend: 'Ext.panel.Panel', alias: 'widget.custpanel', foo: { bar: null }, initComponent: function() { this.callParent(arguments); } }); 

    Но после тестирования все становится странно. Значения наших конфигураций, похоже, волшебным образом меняются. Вот JSFiddle. Случилось так, что все созданные экземпляры ссылаются на один и тот же экземпляр foo . Но в последнее время я сделал это

     store: { fields: [ ... ], proxy: { type: 'direct', directFn: 'Direct.Store.getData' } } 

    с магазином, и это сработало. Так почему же не работает?

    Большинство людей не видят разницы между этим маленьким объектом foo и конфигурацией (ExtJS), которая в основном правильна, потому что оба являются объектами (экземплярами). Но разница в том, что все classы, отправленные sencha, прекрасно знают, какие свойства конфигурации они ожидают и заботятся о них.

    Например, свойство хранилища сетки разрешается StoreManager и поэтому может быть:

    • storeId string, или
    • хранить экземпляр или
    • сохранить конфигурационный объект.

    Во время инициализации сетки любой из них получает разрешение и перезаписывается фактическим экземпляром хранилища. Магазин – всего лишь один пример. Я думаю, что более известным является массив элементов. Это массив во время определения, и он становится переопределенным для каждого экземпляра с помощью MixedCollection (если я не ошибаюсь).

    Да, существует разница между определением classа и созданным им экземпляром. Но нам нужно позаботиться о любом новом свойстве, которое содержит ссылку, такую ​​как foo сверху, и это не так сложно. Вот что нам нужно сделать, чтобы исправить это для примера foo

     Ext.define('Custom', { extend: 'Ext.panel.Panel', alias: 'widget.custpanel', foo: { bar: null }, initComponent: function() { this.foo = Ext.apply({}, this.foo); this.callParent(arguments); } }); 

    Вот JSFiddle

    Теперь мы позаботимся о конфигурации foo при создании экземпляра. Теперь этот пример foo упрощен, и не всегда будет легко разрешить конфигурацию.

    Вывод

    Всегда указывайте определение classа как конфигурации! Они не должны содержать какие-либо упомянутые экземпляры, за исключением простой конфигурации, и должны позаботиться об этом, чтобы разрешить их при создании экземпляра.

    отказ

    Я не претендую на то, чтобы покрыть все это очень короткое письмо!

    Я обычно выступаю за максимально возможную конфигурацию в настройках конфигурации classа, потому что он читает лучше и проще переопределять в подclassах. Кроме того, существует большая вероятность того, что в будущем Sencha Cmd будет иметь оптимизирующий компилятор, поэтому, если вы сохраните свой код декларативным, это может выиграть от оптимизации.

    Для сравнения:

     Ext.define('MyPanel', { extend: 'Ext.grid.Panel', initComponent: function() { this.callParent(); this.store = new Ext.data.Store({ fields: [ ... ], proxy: { type: 'direct', directFn: Direct.Store.getData } }); this.foo = 'bar'; } }); ... var panel = new MyPanel(); 

    А также:

     Ext.define('MyPanel', { extend: 'Ext.grid.Panel', alias: 'widget.mypanel', foo: 'bar', store: { fields: [ ... ], proxy: { type: 'direct', directFn: 'Direct.Store.getData' } } }); ... var panel = Ext.widget({ xtype: 'mypanel', foo: 'baz' }); 

    Обратите внимание, что эти подходы очень разные. В первом примере мы сильно кодируем: значения свойств объекта, конфигурацию хранилища, имя classа MyPanel при его использовании; мы практически убиваем идею classа, потому что он становится нерациональным. Во втором примере мы создаем шаблон, который можно многократно использовать с возможной другой конфигурацией – в основном, это то, о чем вся система classов.

    Однако фактическая разница лежит глубже. В первом случае мы фактически откладываем конфигурацию classа до времени выполнения, тогда как во втором случае мы определяем конфигурацию classа и применяем его на очень разных этапах. На самом деле, мы можем легко сказать, что второй подход вводит что-то, чего не хватает JavaScript изначально: фаза времени компиляции. И это дает нам множество возможностей, которые используются в самом коде фреймворка; если вам нужны примеры, посмотрите Ext.app.Controller и Ext.app.Application в последней версии 4.2.

    С более практической точки зрения второй подход лучше, потому что его легче читать и разбираться. Как только вы поймете эту идею, вы обнаружите, что пишете весь свой код, потому что это просто проще.

    Посмотрите на это так: если вы напишете старое веб-приложение стиля, создавая HTML и прочее на стороне сервера, вы бы попытались не иметь HTML-код с кодом, не так ли? Шаблоны слева, код справа. Это практически то же самое, что и данные initComponent в initComponent : уверен, что он работает, вплоть до точки. Затем он становится чашей спагетти, которую трудно поддерживать и растягивать. О, и все это проверять! Тьфу.

    Теперь есть моменты, когда вам нужно что-то делать с экземпляром во время выполнения, в отличие от времени определения classа – classический пример – использование прослушивателей событий или control вызовом в controllerах. Вам придется взять фактические ссылки на функции из экземпляра объекта, и вы должны сделать это в initComponent или init . Тем не менее, мы работаем над ослаблением этой проблемы – не должно быть жесткого требования жестко кодировать все это; Observable.on() уже поддерживает имена прослушивателей строк и материал MVC тоже, в ближайшее время.

    Как я уже сказал в комментариях выше, мне придется написать статью или руководство для документов, объясняя вещи. Это, вероятно, придется ждать, пока не будет выпущено 4.2; между прочим, этот ответ должен пролить свет на этот вопрос, надеюсь.

    Я искал ответ на тот же вопрос, когда я оказался здесь, и, увидев эти ответы, я разочаровался. Ни один из них не отвечает на вопрос: initComponent () или конструктор?

    Приятно знать, что объекты объекта конфигурации classа являются общими, и вам нужно инициализировать / обрабатывать их на один экземпляр, но код может попасть в конструктор, а также в функцию initComponent ().

    Я предполагал, что конструктор classа Component вызывает initComponent () где-то посередине, и я был не очень прав: просто нужно было посмотреть на исходный код, это на самом деле конструктор AbstractComponent .

    Так выглядит:

     AbstractComponent/ctor: - stuffBeforeIC() - initComponent() - stuffAfterIC() 

    Теперь, если вы расширяете компонент, вы получите что-то вроде этого:

     constructor: function () { yourStuffBefore(); this.callParent(arguments); yourStuffAfter(); }, initComponent: function () { this.callParent(); yourInitComp() } 

    Окончательный порядок, которому они вызваны:

     - yourStuffBefore() - base's ctor by callParent: - stuffBeforeIC() - initComponent: - base's initComponent by callParent - yourInitComp() - stuffAfterIC() - yourStuffAfter() 

    Таким образом, в конечном итоге все зависит от того, хотите ли вы / нужно вводить код между stuffBeforeIC и stuffAfterIC, который вы можете найти в конструкторе classа, который будет расширяться.

    Interesting Posts

    Была предпринята попытка доступа к сокету, запрещенному его разрешениями доступа

    Как связать с паролем в MVVM

    Заголовки уровня 2 с разными стилями

    Спасение возможно поврежденного PDF в Acrobat

    Почему MySQL добавляет функцию, которая противоречит стандартам SQL?

    Элемент прокрутки в виде с seleniumом

    Почему мой шаблон не принимает список инициализаторов

    Как подавить Java-предупреждения для определенных каталогов или файлов, таких как сгенерированный код

    JFreeChart – проблема создания движущейся диаграммы

    Отправьте данные POST с controllerа на другой веб-сайт в Rails

    Создать Out-Of-Process COM в C # /. Net?

    Intel SRT / RST сообщает об ошибке «без загрузочного устройства» после двух перезагрузок

    Как установить сервер по умолчанию для помощников URL-адресов в рельсах?

    jquery: keypress, ctrl + c (или некоторые комбо-подобные)

    Должен ли я войти в Windows при использовании xbootmgr для ускорения загрузки?

    Давайте будем гением компьютера.