【问题标题】:ExtJS 4: Models with Associations and StoresExtJS 4:具有关联和存储的模型
【发布时间】:2011-10-01 03:51:26
【问题描述】:

简介

我在 ExtJS 中遇到了 Ext.data.Model 类的应用程序设计问题。我将在这里尝试将我的想法发展为一个非常常见的在线商店场景,因此您可以关注我。我真的很感激任何关于我的想法和结论的cmets!

型号

假设您想将“每个客户都可以订购多种产品”这一事实映射到 ExtJS。一言以蔽之,可以识别出这三个模型:CustomerOrderProduct。在这种情况下,Order 是连接 Customers 和 Products.

协会

我发现 ExtJS 实际上允许您使用 Ext.data.HasManyAssociationExt.data.BelongsToAssociation 类指定此 (Customer)1-n(Order)1-n(Product) 关系。但这就是人们想要的吗?您是否希望Product 始终属于Order?如果您想要一个Products 列表而与Orders 没有任何联系怎么办?

商店

这是它获得更多 ExtJS 特定的地方。在 ExtJS 中,您有 Ext.data.Stores 来保存您的所有数据。对我来说,组织数据的一种自然方式是为我的每个模型设置一个 Ext.data.Store

  1. CustomerStore
  2. OrderStore
  3. ProductStore

考虑将三个Ext.grid.Panels 并排放置;每个商店一个。在一个网格中选择客户时,他的订单会自动显示在第二个网格中。在第二个网格中选择订单时,相关产品会出现在第三个网格中。

这听起来自然吗?如果没有,请发表评论!

把所有东西放在一起

所以现在我们需要把三件事放在一起:

  1. 模型及其
  2. 协会(hasManybelongsTo)和
  3. 数据 (Stores)

是否可以仅从模型-模型关系的一侧定义关联?例如,我可以指定 Order hasMany Products 但忽略 Product belongsToOrder 吗?因为Product 实际上可以属于多个Order。因此我在下面指定Product模型hasManyOrders。

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'
});

这里是商店:

客户商店

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'
        }
    }
});

订单商店

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'
        }
    }
});

产品商店

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/ 的示例(不是我做的)。它使用两个模型和两个商店,但没有定义关联。

提前谢谢你

-康拉德

【问题讨论】:

  • 您不需要指定关联,我个人不需要。

标签: extjs data-modeling store model-associations


【解决方案1】:

康拉德。我最近面临处理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'}

在此之后,您认为可以通过执行以下操作来使用 Grid1 的 itemclick 上的数据填充 Store2:

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();
}

您期望 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。至少现在。而是使用示例中显示的方法:Model+Store+Filtering。

【讨论】:

  • 嗨分子,谢谢你的回答。我用我的源代码创建了一个 github 存储库。这是我上面描述的问题的完整工作示例,尽管过滤仅在商店的第二次加载时起作用。有点痒,但有点意思。这里是 GitHub 存储库的链接 github.com/kwk/ExtJS-examples
  • 你为什么不直接使用 Grid2.reconfigure(item_which_uses_model1.model2()) ?
  • @Neil,因为我的 store2 不是一个简单的 store,它是一个扩展的。如果我这样做 (item_which_uses_model1.model2()) 它会用新的普通存储替换我的调整存储。
  • 正是我遇到的问题。
【解决方案2】:

我完全同意分子人。通过阅读 ExtJS 文档,当您使用分布到不同商店的树集结构时,它似乎更多地证明了这是一条很好的路线。坦率地说,只有当这种关联以任何方式引用商店来拨打电话时,这一切才可能是真的。从我测试的情况来看,情况并非如此。模型关联没有这种关系。过滤是跟上顺序更新其模型依赖于其他网格的其他网格的最佳方式。

【讨论】:

    【解决方案3】:

    在 ExtJS 4 中一切正常,只是很难第一次就做好。嗯,前几次。

    是的,你可以避免指定children的belongsTo关联,并且仍然在Has Many关系中使用它。

    在我的项目中,我们有几十个模型,其中许多关系很深,而且效果很好。

    关于多对多关系,你应该有

    客户 -- 订单

    这是三个模型,

    或者您可以通过在服务器上进行大量工作来“伪造”它,以假装客户有很多订单。嵌套的 json 可以在这里提供帮助。

    【讨论】:

    • 投票回答。感谢您的博客,加载嵌套模型不再是问题。是否可以保存具有 hasMany 关联的模型?如我所见,当我保存父模型时,未提交嵌套子数据。
    • 有可能。您需要覆盖 JsonWriter.getRecordData() 并在该调用中 Ext.apply(record.data, record.getAssociatedData());然后返回record.data
    • 感谢@Neil。虽然覆盖也是一种选择,但我最终在提交之前直接向我的模型添加了必填字段(我对 Ext JS 开发持乐观态度:)并希望他们在不久的将来实现嵌套模型保存)
    • @bhovhannes ... 博客的链接是什么?我有兴趣看到使用 JsonWriter.getRecordData() 的实现。
    【解决方案4】:

    请注意您的假设:

    (客户)1-n(订单)1-n(产品)

    错了。您的实际模型应该是:

    (客户)1-n(订单)n-n(产品)

    这就是为什么你发现用 hasMany-belongsTo 建模也很困难

    【讨论】:

    • 对于 1 个客户,它是 n 个订单,每个订单包含 n 个产品。关系 n-n 将出现在总概览中,其中永远是 Customer n-n Order n-n Product。在任何情况下,每个开发人员都在等待表记录中的交叉链接,而不是创建 MyRecord 类型的嵌套对象
    猜你喜欢
    • 2012-07-11
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多