2016-11-26 5 views
0

私のプロジェクトでは、バックボーンコレクションを使用してアプリケーションのデータを整理し、自分のデータをローカルストレージに同期させる必要があります。私のデータは2レベルの深いネストされたコレクションとモデルであり、そこに問題が発生します。ネストされたバックボーンのコレクションとモデルをシリアル化する方法は?

内部コレクションがlocalstorageに同期した後、内部コレクションはオブジェクトの生の配列になります。そのため、収集方法(addなど)は使用できません。

のlocalStorageがモデルをシリアライズ、それはmodel.toJSON()呼び出し、それは単に、ネストされたコレクションを除いたモデルの属性をクローン:

は、デバッグとグーグルでの後、私はその理由を見つけました。

// Return a copy of the model's `attributes` object. 
toJSON: function(options) { 
    return _.clone(this.attributes); 
}, 

ので、Underscore's clone functionを使用し、ドキュメントはそれことを言う:

が提供平野オブジェクトの浅いコピーされたクローンを作成します。すべてのネストされた オブジェクトまたは配列は、複製されずに参照によってコピーされます。

したがって、デフォルトモデルの.toJSONをオーバーライドするディープコピー方法を探しています。しかし、私は正しい方法を理解できません。例えば

、私は次のことを試してみました:

Backbone.Model.prototype.toJSON = function() { 
    var json = $.extend(true, {}, this.attributes); 
    return json; 
}; 

エミールの提案に基づいて編集し、私の本当のモデルには、以下のようになります:オーバーライドした後

app.RecordItem = Backbone.Model.extend({ 

    defaults: { 
     target: 1, 
     date: '', 
     day: '', 
     //foodlist: new TrackList(), 
     currentvalue: 0, 
     isSetup: false, 
    }, 
    initialize: function() { 

     var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; 
     var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; 
     var d = new Date(); 
     this.set("date", d.getDate() + "." + months[d.getMonth()]); 
     this.set("day", days[d.getDay()]); 
     // 
     var foodlist = this.getFoodlist(); 
     if (!(foodlist instanceof TrackList)) { 
      this.set('foodlist', new TrackList(foodlist)); 
     } 
    }, 
    getFoodlist: function() { 
     if (!this.foodlist) this.foodlist = new TrackList(this.get('foodlist')); 
     return this.get('foodlist'); 
    }, 

    toJSON: function(options) { 
     // this gets the default behavior 
     var attrs = this.constructor.__super__.toJSON.apply(this, arguments); 
     var foodlist = attrs.foodlist; 
     if (foodlist) { 
      // then replace the collection reference with the actual serialized data 
      attrs.foodlist = foodlist.toJSON(options); 
     } 
     return attrs; 
    }, 
}); 

toJSON方法。 JSONにシリアライズするのに必要ですので

localStorage店舗列:jQuery's extendは深いコピーを提供するが、エラーメッセージは、それはあなたが必要なものではありませんし、ここに理由です、

"foodlist.toJSON is not a function(…)" 

答えて

1

です。関数はJSON で有効ではないため、シリアル化されません。

だから、全体のバックボーンコレクションまたはモデルをシリアル化しようとすると、代わりに、データのみをシリアル化し、

Backbone's toJSON

データをデシリアライズするとき、ネストされた構造をバックインスタンス化するのは良い考えではありませんこれは永続化、シリアライゼーション、またはサーバに送信される前に拡張のために使用することができます。 このメソッドの名前は実際にはJSON文字列を返さないため、ビット が混乱していますが、 はJavaScript API for JSON.stringify が動作することを恐れています。

デフォルトのtoJSONの動作は、モデルの属性のシャローコピーを作成することです。モデルとコレクションを入れ子にしているので、入れ子を考慮に入れて直列化を変更する必要があります。

簡単な方法は、toJSONをオーバーライドして、attributesハッシュ内のすべてのネストされたコレクションとモデルのtoJSON関数を呼び出すことです。

var Daymodel = Backbone.Model.extend({ 
    defaults: { day: 1, }, 
    initialize: function(attrs, options) { 
     var agenda = this.getAgenda(); 
     if (!(agenda instanceof Todocollection)) { 
      // you probably don't want a 'change' event here, so silent it is. 
      return this.set('agenda', new Todocollection(agenda), { silent: true }); 
     } 
    }, 
    /** 
    * Parse can overwrite attributes, so you must ensure it's a collection 
    * here as well. 
    */ 
    parse: function(response) { 
     if (_.has(response, 'agenda')) { 
      response.agenda = new Todocollection(response.agenda); 
     } 
     return response; 
    }, 
    toJSON: function(options) { 
     var attrs = Daymodel.__super__.toJSON.apply(this, arguments), 
      agenda = attrs.agenda; 
     if (agenda) { 
      attrs.agenda = agenda.toJSON(options); 
     } 
     return attrs; 
    }, 
    getAgenda: function() { 
     return this.get('agenda'); 
    }, 
    setAgenda: function(models, options) { 
     return this.getAgenda().set(models, options); 
    }, 
}); 

追加情報:

  • How to handle nested collections and models
  • Backbone.localStorage、メンテナンスされていないが、良いスタート。

    文字列に機能をシリアル化するとevalでそれをデシリアライズすることは不可能ではない、それは良い考えではありませんし、ここでは完全に不必要なものの

  • Modified Backbone sync function which handles localStorage
  • +0

    こんにちはエミール、私の2つの投稿された質問のすべてのこれらの情報ありがとう。しかし、私はまだ正しい動作を与えることはできません。私の更新された編集をご覧ください。 –

    +0

    @baoqgerあなたは1つに2つのソリューションを混ぜた、それは動作するはずですが、あなたは1つを使用する必要があります。 'parse'をオーバーライドする方法をデモンストレーションし、属性が常にコレクションであることを実証するために、[私の他の答え](http://stackoverflow.com/a/40823148/1218980)を更新しました。 –

    関連する問題