Я так и не нашел окончательного ответа на этот вопрос от Sencha, когда начинал работу с MVC, но я могу рассказать вам, что я успешно делал для нескольких приложений.
Я создаю и загружаю свои магазины в соответствии с тем, как они используются. Кажется, для меня это разделилось на три разные категории:
Магазины, применимые ко всему приложению
Хранилища, которые применяются ко всем экземплярам представления
Магазины, привязанные к одному экземпляру представления
<сильный>1. Магазины, применимые ко всему приложению
Обычно у меня есть «основной» контроллер, который управляет структурой моего приложения, такими вещами, как навигация с помощью клавиатуры, главное меню и т. д.
Магазины, попадающие в первую категорию выше, помещаются в массив stores
этого «основного» контроллера. Если эти магазины не зависят от другого магазина, я просто делаю их autoLoad: true
и с ними покончено. Но в тех случаях, когда они зависят от данных другого хранилища, я добавляю прослушиватель в родительское хранилище, чтобы загрузить зависимое хранилище внутри родительского события onLoad
.
Примером некоторых магазинов, попадающих в эту первую категорию, являются эталонные магазины, которые я использую в полях со списками по всему приложению, обычно во многих различных типах представлений. Обычно они настраиваются с помощью autoLoad: true
, после чего я больше никогда не загружаю их для сеанса этого пользователя. Всякий раз, когда мне нужно поле со списком, которое использует хранилище ссылок, я могу настроить его следующим образом:
{
xtype: 'combobox',
allowBlank: false,
forceSelection: true,
store: Ext.getStore('SomeReferenceStore'),
queryMode: 'local', // this makes sure the store doesn't reload
valueField: 'id',
displayField: 'name'
}
Чтобы привести пример двух магазинов, которые попадают в первую категорию, причем один зависит от другого:
В одном из моих приложений у меня есть динамическое количество пользовательских разрешений, когда пользователь входит в приложение, мне нужно было получить различные разрешения и изменить модель User
, чтобы включить логическое поле для каждого из этих разных разрешений:
Ext.define('MyApp.controller.Main', {
extend: 'Ext.app.Controller',
models: [
'User',
'Reference',
// etc...
],
stores: [
'CurrentUser',
'PermissionRef', // this is "autoLoad: true"
// etc...
],
init: function() {
var me = this;
// update the user model and load the user
me.getPermissionRefStore().on('load', function(store, records) {
var model = me.getUserModel(),
fields = model.prototype.fields.getRange();
// append the permissions onto the User model fields
Ext.each(records, function(permission) {
fields.push({
name: permission.get('name'),
type: 'bool',
});
});
// update the user model with the permission fields
model.setFields(fields);
// load the current user
me.getCurrentUserStore().load();
// other stuff...
});
// other stuff...
}
});
При этом всякий раз, когда мне нужна ссылка на пользователя и какие разрешения у него есть, я просто вызываю:
var user = Ext.getStore('CurrentUser').first();
Иногда представление также будет зависеть от загружаемого хранилища. Например, пункты моего главного меню определяются таблицей базы данных, в этом случае я бы включил прослушиватель onLoad
таким же образом (внутри функции init
контроллера):
// create the menu once we know what menu items are available
me.getMenuStore().on('load', function(store) {
me.getViewport().add(Ext.widget('mainpanel'));
});
Сам MyApp.store.Menu
будет настроен с autoLoad: true
.
<сильный>2. Хранилища, которые применяются ко всем экземплярам представления
Я создаю и загружаю их так же, как и первую категорию, только помещаю их в массив stores
конкретного контроллера view вместо массива stores
контроллера «Main».
Тогда это та же основная концепция, некоторые autoLoad: true
некоторые нет, если они зависят от данных другого хранилища.
Для тех, которые не являются autoLoad: true
, они загружаются где-то внутри функции init
контроллера или в результате запуска какого-либо события.
<сильный>3. Магазины, привязанные к одному экземпляру представления
Здесь я могу пойти против структуры MVC, но на самом деле нет лучшего места для хранилища, которое применяется к одному экземпляру представления, чем внутри самого представления.
В большинстве случаев я даже не помещаю эти хранилища в массив stores
контроллера представления. Я просто создаю и загружаю их внутри функции представления initComponent
. В результате этого, когда представление уничтожается, больше нет ссылки на хранилище, поэтому хранилище также будет уничтожено. Это помогает сократить ресурсы для магазинов, которые могут создаваться много раз.
Например, предположим, что у вас есть MyApp.view.UnicornWeightGrid
, который расширяет gridpanel
и показывает прогрессивный вес единорога с течением времени. Пользователь может открыть UnicornWeightGrid
для всех единорогов в мире для сравнения и перекрестных ссылок. Будет столько разных экземпляров UnicornWeightStore
, сколько экземпляров UnicornWeightGrid
.
Представление может быть определено следующим образом:
Ext.define('MyApp.view.UnicornWeightGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.unicornweight',
requires: [
'MyApp.model.UnicornWeight'
],
closable: true,
initComponent: function() {
var me = this;
me.store = Ext.create('Ext.data.Store', {
model: 'MyApp.model.UnicornWeight',
proxy: {
type: 'ajax',
url: 'unicorns/weight',
extraParams: {
name: me.unicornName
}
}
});
me.store.load();
});
});
Затем всякий раз, когда мы хотим получить другой UnicornWeightGrid
, мы можем просто вызвать:
var grid = Ext.widget('unicornweight', {
unicornName: someUnicornNameVariable
});
myTabPanel.add(grid);
Любые прослушиватели onLoad
, которые мне нужны в хранилищах, определенных в представлении, я также прикрепляю внутри представления. Так что мне действительно не нужна ссылка где-либо еще.
С учетом всего сказанного, это ни в коем случае не единственный способ настроить свои магазины.
Я обнаружил, что это наиболее работоспособный способ последовательной обработки хранилищ при создании нескольких различных приложений ExtJS «MVC», но иногда я делаю это по-разному, в том числе в «особых» случаях.
Вы должны иметь в виду, что «MVC» — это довольно свободный шаблон проектирования, он определяется и реализуется по-разному почти в каждом фреймворке, который я использовал. Таким образом, вы можете делать то, что лучше всего подходит для вас.
person
egerardus
schedule
24.08.2012