5 Stimmen

Organisieren Sie Modell und Sammlung im Backbone

Ich habe eine JSON-Antwort mit der folgenden Struktur:

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

Kann ich damit eine Sammlung machen? Die ID, der Status usw. sind nur Metadaten. Oder sollte ich eine neue ItemsCollection für das Array items? Werde ich auch benachrichtigt, wenn sich ein Element geändert hat?

6voto

umar Punkte 900

Ja, Sie sind auf dem richtigen Weg. Sie müssen lediglich drei Dinge definieren:

  1. A Model für Ihre order Objekt
  2. A Model für die order_item Objekt
  3. A Collection para order_item s

Denken Sie daran, dass jeder Model ist für seine eigene Validierung verantwortlich, daher müssen Sie eine Validierungsfunktion für sie schreiben.

Dann wird jedes Mal, wenn Sie Ihr JSON parsen, in Ihrem Element der parse Methode, müssen Sie die order_item s zu einem Backbone Collection mit etwas wie:

parse: function(response) {
    if (!_.isNull(response) && !_.isNull(response.orderitems)) {
        response.orderitems = new OrderItems(response.orderitems);
    }
    return response;        
}

Wenn Sie dies getan haben, sollte alles wie vorgesehen funktionieren!

3voto

Derick Bailey Punkte 70483

Sie können all das tun, aber Sie müssen es selbst oder mit einem Plugin tun. Die Chancen stehen gut, dass der Code, den Sie am Ende schreiben, dem ähnelt, der im Backbone.Relational Plugin verfügbar ist:

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

Ich empfehle, dieses Plugin zu verwenden, anstatt den Code selbst zu ändern.

3voto

Luke Punkte 7920

Wie in Backbone beschrieben ( http://backbonejs.org/#FAQ-nested ) sollten Sie die folgende Methode verwenden...

Edit: Sie benötigen keine Plugins. Außerdem empfehle ich dies nicht, da man bei Backbone sicher sein kann, dass man ein grundsolides Framework hat, aber sie überprüfen nicht, wie grundsolide jedes Plugin ist, das sie auf ihrer Website verbreiten. Ich hatte viele Projekte, bei denen ich über Verschachtelung nachdenken musste. Am Ende war der hier gezeigte Weg der sicherste und konventionellste.

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

Verbindlich

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

myOrder.on("...");

Zugang

Zugriff auf Ihre Bestellung aus den OrderItems heraus.

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

Langsames Laden

Manchmal wollen wir nicht alles in einer einzigen Anfrage laden. Meistens ziehe ich es vor, die Basissammlung zu laden, und nur wenn eine Ansicht ein Modell lädt und das Modell Untersammlungen hat, rufe ich sie später ab. Hierfür habe ich eine fetchOnce-Methode.

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

An anderer Stelle würden Sie dann Ihre kompletten Aufträge initialisieren und abrufen.

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

Wenn Sie dann eine Bearbeitungsansicht aufrufen und möchten, dass auch alle Auftragspositionen angezeigt werden, müssen Sie Folgendes tun.

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

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

da fetchOnce ein neues Deferred zurückgibt, wenn es nicht vorhanden ist, oder ein vorhandenes (wegen _.once) können Sie immer an es binden, wenn es bereits zuvor aufgerufen wurde, werden Sie in der done auch benachrichtigt werden...

0voto

Justin Alexander Punkte 1954

Sie können sie auch dynamisch definieren:

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

Jede Änderung an der zurückgegebenen Sammlung würde automatisch das übergeordnete Modell aktualisieren. Hinweis: Das übergeordnete Modell kann nur auf Änderungen an "order_items", nicht aber an seinen Kindern reagieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X