ExtJS 4 MVC множественные экземпляры представлений и трудности подчиненного / дочернего контроллера - PullRequest
14 голосов
/ 29 ноября 2011

Я столкнулся с проблемой с шаблоном MVC в ExtJS 4. По крайней мере, я думаю, что у меня есть. Обратившись к нескольким людям с этим вопросом и неоднократно размещая сообщения на форумах Sencha, я обращаюсь к более широкой аудитории в надежде получить либо лампочку, либо подтверждение.

Проблема

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

Это приложение является одностраничным приложением Javascript на стороне клиента.

Модель ExtJS 4 MVC предполагает, что вы определите все свои контроллеры в своем классе Application. Эти контроллеры затем инициализируются при загрузке приложения. Контроллеры отслеживают просмотры, модели и магазины.

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

Я реорганизовал свое приложение, добавив новые методы-прототипы в Компонент и Контроллер, чтобы учесть а) вспомогательные контроллеры (некоторые из моих контроллеров становились довольно большими) и б) определение хранилищ специально для представления, с которым они работают. Модели все еще могут быть определены на контроллере, просто для удобства использования обработчиками, если вам нужно сделать что-то вроде получения записи с сервера.

Вопрос

Мое понимание MVC привело бы меня к мысли, что модели более непосредственно связаны с View, чем с Controller. Я предполагаю, что ExtJS 4 решает присоединить хранилища (которые, я думаю, можно рассматривать как обертки к более классической модели) к контроллерам с целью поощрения повторного использования загруженных данных и оптимизации от множества копий экземпляр того же класса. Однако мне кажется, что этого нельзя сделать, если намереваться иметь много экземпляров представления, доступных для пользователя. На мой взгляд, наличие множества экземпляров является важной опцией в OO-инфраструктуре, поэтому я остановил тенденцию и реализовал прототипы в некоторых базовых классах Ext. (Спасибо, Ext.implement!).

Есть ли способ иметь несколько одновременных экземпляров представления с различными данными, загруженными в них , используя готовые классы MVC и используя предоставленные установщики, получатели и т. Д.?

Ответы [ 7 ]

8 голосов
/ 02 мая 2012

Я столкнулся с похожей проблемой:

Рассмотрим панель вкладок для приложения типа CRM, которая открывает новые экземпляры представления для каждого клиента.И предположим, что представление вкладок содержит 3 или 4 панели сетки редактирования строк для взаимодействия с различными наборами данных, относящихся к этому клиенту.

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

Для работы с несколькими экземплярами одного и того же хранилища, необходимого для этого, я принял это близко к сердцу из этого поста:

Для экземпляра Store в представлении или глобального ... зависит от потребностей.Если вы собираетесь использовать глобально, сделайте его глобальным.Если вам это понадобится только в представлении, поместите его в представление.MVC не является законом, вы можете изменить его в соответствии со своими потребностями.Технически предполагается, что часть контроллера в MVC является посредником между частями просмотра и модели, но иногда это просто не нужно.Я создаю Магазин в представлении 95% времени.Я приведу вам пример ...

Если у вас есть Магазин для продуктов, вам, вероятно, нужно только сослаться на этот Магазин в вашей Грид.Это обычно не требуется для других частей приложения.Однако, если у вас есть Магазин для загрузки стран, мне часто нужно его глобально, поэтому мне нужно загрузить его только один раз, и затем я могу установить / использовать этот Магазин в нескольких представлениях.

Так что я просто создалнеобходимое хранилище, которое конкретно относится к экземпляру представления, внутри метода initComponent представления.В приложении было несколько глобальных хранилищ, которые я создал как классы хранилищ, следуя рекомендациям MVC.Это хорошо сработало, чтобы инкапсулировать хранилища экземпляров представления внутри представления.Тогда мне был нужен только один экземпляр контроллера.

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

2 голосов
/ 05 ноября 2012

Это можно сделать достаточно легко. Вам необходимо соблюдать несколько правил:

  1. загрузка ваших контроллеров при запуске приложения. Не выгружайте их. Не беспокойтесь о памяти или времени, она довольно мала даже для сотен контроллеров, если вы минимизируете и объединяете свои js.

  2. Никогда не используйте refs или views свойства контроллера. Вы собираетесь использовать один экземпляр контроллера, но несколько экземпляров представлений, поэтому вам никогда не понадобится ссылка на представление.

  3. использовать только прослушиватели событий в контроллерах. Вы будете только слушать события по вашему мнению. Вы всегда можете получить (временную) ссылку на представление в обработчике события через параметр "cmp" в обработчике.

  4. Чтобы «запустить» представление, создайте его и добавьте в другое представление. Чтобы уничтожить это, уничтожьте это. Вы не используете контроллер для запуска представления. Вы можете использовать события afterrender и beforedestroy в контроллере для добавления логики.

2 голосов
/ 05 декабря 2011

Я не думаю, что вам когда-либо понадобится более одного экземпляра контроллера, независимо от того, сколько у вас видов / моделей.Смотрите функциональный пример здесь:

http://whatisextjs.com/extjs-4-extension/fieldset-w-dynamic-controls-7

1 голос
/ 14 ноября 2012

В ExtJS 'MVC контроллер для вас является Singleton. Мне нравится, как DeftJS думает о MVC. Каждый экземпляр представления имеет собственный экземпляр контроллера. Таким образом, вы можете поместить все «управляющие правила» в контроллер для определенной части вашего представления, и это будет реализовано только при открытии представления.

У меня не было опыта, как я мог использовать несколько приложений Defts JS в одном проекте.

0 голосов
/ 21 марта 2013

Проверить это сообщение . Идея заключается в том, чтобы взять некоторую конфигурацию (например, store и itemId) из view config и поместить ее в конфигурацию viewport:

// .../app/view/Viewport.js
Ext.define('MyApp.view.Viewport', {
    // ...
    items: [
        // ...
        { xtype: 'testview', store: 'Store1', itemId: 'instance1' },
        { xtype: 'testview', store: 'Store2', itemId: 'instance2' }
    ]
});

Проблема с магазином будет решена, очевидно. Различные itemId s позволят вам правильно обрабатывать события.

0 голосов
/ 07 декабря 2011

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

Ext.define('MyApp.grids.something',{
extends:'Ext.grid.panel' 
//...

Эти классы предопределены.Затем, когда контроллер или представление загружают эту сетку, они используют

var grid=Ext.create('MyApp.grids.something',{id:'unique',store:mystore});

Как вы можете видеть, мы можем передавать различные параметры конфигурации в одну и ту же сетку каждый раз, когда она создается.Мы можем относиться к этому точно так же, как и к

Ext.create('Ext.grid.Panel');

За исключением того, что мы предварительно настроили некоторые параметры, а некоторые нельзя переопределить и т. Д.

Надеюсь, это помогло.

0 голосов
/ 01 декабря 2011

Конечно.Что заставило вас поверить в обратное?Вот пример создания пользовательского представления, которое расширяется из компонента Window.Вы можете запускать этот метод много раз с одного и того же контроллера, и каждый раз вы будете получать новый экземпляр View.

«this» относится к контроллеру, в котором выполняется код:

       this.getRequestModel().load(requestID,{       //load from server (async)
                 success: function(record, operation) {
                        var view = Ext.widget('requestEdit',{
                            title: 'MyRequest '+requestID
                        });
                        var form = view.down('form');
                        form.loadRecord(record);
                 }
         });
...