在骨干中组织模型和集合

时间:2011-10-02 21:12:24

标签: json backbone.js

我有一个JSON响应,其结构如下:

{
    id: 1,
    status: 0,
    created_at: "Y:m:d H:m:s",
    updated_at "Y:m:d H:m:s)",
    order_items: [items]
}

我能用它制作一个集合吗? ID,状态等只是元数据。或者我应该为items数组创建新的ItemsCollection吗?当项目发生变化时,我也会收到通知吗?

4 个答案:

答案 0 :(得分:6)

是的,你走在正确的轨道上。你只需要定义三件事:

  1. Model对象的order
  2. Model对象的order_item
  3. Collection的{​​{1}}
  4. 请记住,每个order_item都负责自己的验证,因此您需要为其编写验证函数。

    然后,每次解析JSON时,在项目的Model方法中,您需要使用以下内容将parse转换为主干order_item

    Collection

    一旦你完成了这一切,一切都应该按预期工作!

答案 1 :(得分:3)

你可以做所有这些,但你必须自己或使用插件。很有可能,你最终编写的代码将与Backbone.Relational插件中的代码类似:

http://github.com/PaulUithol/Backbone-relational

我建议使用该插件而不是自己滚动代码

答案 2 :(得分:3)

如Backbone(http://backbonejs.org/#FAQ-nested)所述,您应该使用以下方式...

编辑:您不需要任何插件。此外我不建议这样做,因为Backbone你可以确定你有一个坚如磐石的框架,但他们不会检查他们在他们的网站上传播的任何插件是如何坚如磐石。我有很多项目需要考虑嵌套。最后,这里显示的方式是最安全和最传统的。

Strucutre

var Order = Backbone.Model.extend({
   initialize : function(data) {
      this.orderItems = new OrderItems(null, {order:this});
      if (!!data.order_items) {
          this.orderItems.reset(data.order_items, {parse:true});
          //we dont want nesting in "attributes"
          this.unset("order_items");
      }
   },
   // this is used, when a change from server happens. So when
   // the model already exists, and the stuff in initialize
   // wouldnt be called anymore.
   parse : function(data) {
       if (!!data.order_items) {
           this.orderItems.reset(data.order_items);
           delete data.order_items;
       }
       return data;
   }
});

var Orders = Backbone.Collection.extend({
   model : Order
});

var OrderItem = Backbone.Model.extend({

});

var OrderItems = Backbone.Collection.extend({
   model : OrderItem,
   initialize : function(data, options) {
      if (options && options.order) {
          this.order = options.order;
      } 
   }
};

结合

myOrder.orderItems.on("...");

myOrder.on("...");

访问

从OrderItems中访问您的订单。

var someOrderItem = myOrders.get(1).orderItems.first();
someOrderItem.collection.order === myOrders.get(1)
// will result in "true"

延迟加载

有时我们不想在一个请求中加载所有内容。大多数时候我更喜欢加载基本集合,并且只有当视图加载一个模型,并且模型有子集合时,我才会在以后检索它们。为此,我有一个fetchOnce方法。

var OrderItems = Backbone.Model.extend({
    initialize : function() {
        if (options && options.order) {
           this.order = options.order;
        }
        this.fetchOnce = _.once(this.fetch, this);
        //this will always return you an jquery xhr deferred.
    },
    url : function() {
        if (this.order) {
           // url() would return you something like "/order/1234"
           return this.order.url() + "/items"
        }
    }
);

然后在其他地方,您将初始化并获取完整的订单。

   var orders = new Orders();
   orders.fetch();

如果您随后进行了一些编辑视图并希望所有订单商品也存在,那么您可以执行以下操作。

   var view = new Backbone.View({
      order : orders.get(1)
   });

   view.order.orderItems.fetchOnce().done(function() {
       view.render();
   });

因为fetchOnce返回一个新的延迟,如果不存在,或者一个现有的(因为_.once)你总是可以绑定它,如果之前已经调用过,你也会在完成时通知你...

答案 3 :(得分:0)

您也可以动态定义它:

var Order = Backbone.Model.extend({
   initialize: function () {
      this.getItems = _.memoize(this.getItems); // not necessary, but improves performance
   },
   getItems: function () {
     var that = this; 
     var col = new Backbone.Collection(this.get('order_items'));
     col.on('change', function() {
                          that.set({order_items: this.toJSON()});
                      });
     return col;
   }
})

对返回的集合的任何更改都将自动更新父模型。注意:父模型只能监听'order_items'的变化而不是它的子节点。