2016-11-26 75 views
0

在我的項目中,我使用Backbone集合來安排應用程序的數據,並且還需要將我的數據同步到localstorage。我的數據是一個兩層深的嵌套集合和模型,並且存在問題發生的地方。如何序列化嵌套的Backbone的集合和模型?

內部集合與localstorage同步後,它將成爲對象的原始數組。所以收集方法(如add)不能使用。

調試和google搜索後,我找到了原因:

當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方法。該錯誤消息是

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

回答

1

雖然jQuery's extend提供深拷貝,這不是你所需要的,這裏的原因:

localStorage存儲字符串,所以它需要序列化到JSON。功能將不會被序列化,因爲它們在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); 
    }, 
}); 

其他信息:


雖然不是不可能的序列化到一個字符串的函數,並與eval反序列化它,這不是一個好主意,完全沒有必要在這裏。

+0

嗨Emile,感謝所有這些信息在我的兩個發佈的問題。但我仍然無法給出正確的行爲。請看我更新的編輯。 –

+0

@baoqger你把2個解決方案混合成一個,而它應該工作,你只需要使用一個。我更新了[我的其他答案](http://stackoverflow.com/a/40823148/1218980)來演示如何重寫'parse'並確保該屬性始終是一個集合。 –