ExtJS 4: модели с ассоциациями и магазинами - PullRequest
32 голосов
/ 08 июля 2011

Введение

Я сталкиваюсь с проблемой проектирования приложений с классом Ext.data.Model в ExtJS. Я постараюсь развить свои идеи до очень распространенного сценария интернет-магазина, чтобы вы могли следовать за мной. Буду очень признателен за любые комментарии по поводу моих мыслей и выводов!

Модель

Предположим, вы хотите сопоставить тот факт, что " Каждый клиент может заказать несколько продуктов " в ExtJS. Из простых слов можно выделить эти три модели: Customer, Order и Product. Order в этом случае соединяет Customer и Product s.

ассоциации

Я обнаружил, что ExtJS на самом деле позволяет вам определять это отношение (Customer)1-n(Order)1-n(Product), используя классы Ext.data.HasManyAssociation и Ext.data.BelongsToAssociation. Но это то, что вы хотите? Хотели бы вы, чтобы Product всегда принадлежало Order? Что, если вы хотите иметь список Product с без какого-либо подключения к Order с?

Магазины

Вот где он более специфичен для ExtJS. В ExtJS у вас есть Ext.data.Store s для хранения всех ваших данных. Для меня естественным способом организации моих данных является наличие Ext.data.Store для каждой из моих моделей:

  1. CustomerStore
  2. OrderStore
  3. ProductStore

Подумайте о наличии трех Ext.grid.Panel рядом; по одному на каждый магазин. При выборе клиента в одной сетке его заказы автоматически отображаются во второй сетке. При выборе заказа во второй сетке связанные продукты появляются в третьей сетке.

Это звучит нормально для вас? Если нет, пожалуйста, прокомментируйте!

Собираем все вместе

Итак, теперь у нас есть три вещи, которые нам нужно объединить:

  1. Модели и их
  2. Ассоциации (hasMany, belongsTo) и
  3. Данные (Store с)

Можно ли определить ассоциацию только с одной стороны отношения Модель-Модель? Например, могу ли я указать, что Order hasMany Product s, но не указывать, что Product belongsTo an Order? Потому что Product может на самом деле принадлежать более чем одному Order. Поэтому я указываю, что Product модель hasMany Order s ниже.

Вот модели в ExtJS:

Клиент

Ext.define('Customer', {
    extend   : 'Ext.data.Model',
    requires : [
        'Order',
    ],
    fields   : [
           {name : 'id',          type : 'int'},
           {name : 'lastname',    type : 'string'}
           {name : 'firstname',   type : 'string'}
    ],
    hasMany: 'Order' /* Generates a orders() method on every Customer instance */
});

Заказать

Ext.define('Order', {
    extend   : 'Ext.data.Model',
    fields   : [
            {name : 'id',          type : 'int'},
            {name : 'customer_id', type : 'int'}, /* refers to the customer that this order belongs to*/
            {name : 'date',        type : 'date'}
    ],
    belongsTo: 'Customer', /* Generates a getCustomer method on every Order instance */
    hasMany: 'Product' /* Generates a products() method on every Order instance */
});

Продукт

Ext.define('Product', {
    extend   : 'Ext.data.Model',
    fields   : [
            {name : 'id',          type : 'int'},
            {name : 'name',        type : 'string'},
            {name : 'description', type : 'string'},
            {name : 'price',       type : 'float'}
    ],
    /*
        I don't specify the relation to the "Order" model here
        because it simply doesn't belong here.

        Will it still work?
    */
    hasMany: 'Order'
});

А вот и магазины:

CustomerStore

Ext.define('CustomerStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'CustomerStore',
    model       : 'Customer',
    proxy   : {
        type   : 'ajax',
        url    : 'data/customers.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

OrderStore

Ext.define('OrderStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'OrderStore',
    model       : 'Order',
    proxy   : {
        type   : 'ajax',
        url    : 'data/orders.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

ProductStore

Ext.define('ProductStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'ProductStore',
    model       : 'Product',
    proxy   : {
        type   : 'ajax',
        url    : 'data/products.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

Вот пример (не мной) с компаниями и их продуктами http://superdit.com/2011/05/23/extjs-load-grid-from-another-grid/. Он использует две модели и два магазина, но нет никаких ассоциаций, определяющих.

Заранее спасибо

-Konrad

Ответы [ 4 ]

14 голосов
/ 31 июля 2011

Konrad.Недавно я столкнулся с проблемой Models+Associations+Stores.Это был не очень приятный опыт.Вот что я узнал:

Допустим, у нас есть Store1, Store2, Model1, Model2, Grid1, Grid2.Grid1 использует Store1, Store1 использует Model1 и аналогично Grid2 использует Store2, Store2 использует Model2.

Пока все работает, данные загружаются и т. Д.

Но теперь мы хотим добавить hasMany связь с Model1.Хорошо, мы добавляем в конфигурацию Model1:

hasMany: {model: 'Model2', name: 'model2'}

После этого вы думаете, что вы можете заполнить Store2 данными в Grid1 itemclick, выполнив что-то вроде:

Grid1.on('itemclick', function(view, item_which_uses_model1){
  //item_which_uses_model1.model2() supposed to return Model2's store
  item_which_uses_model1.model2().load();
}

Youожидаем, что Grid2 заполнен данными о Grid1 itemclick.Но ничего не происходит.Актуальные запросы публикуются, ответы получены.Но Grid2 не заполнен данными.
И через некоторое время вы понимаете, что item_which_uses_model1.model2() НЕ Store2.

, когда Model2 «видит», что она связана сModel1 создает собственный магазин Model1, который не равен Store2.

Это не круто, потому что Grid2 использует Store2.

На самом деле вы можете взломать его, например, добавив в конфигурацию Grid2:

store: new Model1().model2(),

но что, если вы используете шаблон ExtJS mvc.Grid2 не нужно ничего знать о Model1.

Я не рекомендую , используя associations в реальных проектах.По крайней мере, сейчас.Вместо этого используйте подход, который показан в вашем примере: Модель + Магазин + Фильтрация.

9 голосов
/ 25 мая 2012

В ExtJS 4 все отлично работает, с первого раза сложно разобраться. Ну, первые несколько раз.

Да, вы можете избежать указания принадлежности к ребенку и при этом использовать ее в отношении "Имеет много".

В моем проекте у нас есть десятки моделей, многие из которых имеют глубокие отношения, и это прекрасно работает.

Относительно отношений Много-Много, у вас должно быть либо

Клиент - - Заказ

Это три модели,

Или вы можете «подделать» его, выполнив кучу работы на сервере, чтобы притвориться, что клиент HasMany Orders Вложенный JSON может помочь здесь.

3 голосов
/ 24 мая 2012

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

0 голосов
/ 23 января 2013

Обратите внимание, что ваше предположение:

(Заказчик) 1-п (Order) 1-п (продукт)

неправильно. Ваша фактическая модель должна быть:

(Заказчик) 1-п (Order) п -n (Product)

Вот почему вы также столкнулись с трудностями при моделировании его с помощью hasMany-ownTo

...