我正在使用Backbone.js构建应用程序。我的一些服务器端API将在特定时间后返回所有新的或更改的模型。其中一些对象对我的收藏可能是新的,所以我可以添加它们。其他可能已经存在,在这种情况下,我想更新现有的模型。所以基本上我正在寻找upsert(更新或插入)功能。
这类似于0.9.0中添加的{add:true}选项,除了我还想要更新。
有一种简单/已知的方法可以做到这一点吗?更新代码似乎并不难,但我不想重新发明轮子。
答案 0 :(得分:5)
我用通用方法解决了这种情况:
App.Utils = {
refreshCollection: function( collection, collectionJSON ){
// update/add
_( collectionJSON ).each( function( modelJSON ) {
var model = collection.get( modelJSON.id );
if( model ) {
model.set( modelJSON );
} else {
collection.add( modelJSON );
}
});
// remove
var model_ids_to_keep = _( collectionJSON ).pluck( "id" );
var model_ids = collection.pluck( "id" );
var model_ids_to_remove = _( model_ids ).difference( model_ids_to_keep )
_( model_ids_to_remove ).each( function( model_id_to_remove ){
collection.remove( model_id_to_remove );
});
},
}
collection
:是一个Backbone.Collection collectionJSON
:是一个包含哈希样式的模型数据的数组。典型的JSON响应。我确信它可以进行优化,尤其是删除部分。但由于我仍在进行测试,因此可读性我保持这样。
// code simplified and no tested
var VolatileCollection = Backbone.Collection.extend({
// url:
// model:
// so on ...
})
var PersistentCollection = Backbone.Collection.extend({
// url: not needed due this Collection is never synchronized or changed by its own
// change the VolatileCollection instead, all changes will be mirrored to this Collection
// through events
// model: the same
initialize: function( opts ){
this.volatileCollection = opts.volatileCollection;
this.volatileCollection.on( "reset", this.update, this );
this.volatileCollection.on( "change", this.update, this );
}
update: function(){
App.Utils.refreshCollection( this, this.volatileCollection.toJSON() );
}
})
var volatileCollection = new VolatileCollection();
var persistentCollection = new PersistentCollection({ volatileCollection: volatileCollection });
volatileCollection.fetch();
答案 1 :(得分:3)
注意:这个答案是为Backbone v0.9编写的。从那时起,Backbone v1.0已经发布,其中包含collection.set()
描述的//**upsert** takes models and does an update-or-insert operation on them
//So models that already exist are updated, and new models are added
upsert: function (models, options) {
var self = this;
options || (options = {});
models = _.isArray(models) ? models.slice() : [models];
var addModels = [];
_.each(models, function (newModel) {
var n = self._prepareModel(newModel, options);
var existingModel = self.get(n.id);
if (existingModel) {
existingModel.set(n, options);
} else {
addModels.push(n);
}
});
if (!_.isEmpty(addModels)) {
self.add(addModels, options);
}
}
方法。这可能是一个更好的解决方案。
周末我将自己的版本整合在一起。我会把它放在这里以防其他人找到这个帖子,但我仍然很高兴看到任何其他可能存在的解决方案。
我通过修改Backbone.js源来做到这一点,这不一定是个好主意,但它很容易。有两个更改,首先将此函数添加到Backbone.Collection原型:
collection[options.add ? 'add' : (options.upsert ? "upsert" : 'reset')](collection.parse(resp, xhr), options);
然后修改Backbone.Collection.fetch()函数中的一行来读取:
fetch({upsert:true})
这允许您致电{{1}}以获取我正在寻找的行为。