Backbone.Collection.merge
大厦@杰布的响应上面,我已经封装这种行为为骨干的扩展,你可以复制并粘贴到.js([选项])文件并包含在您的页面中(在包含Backbone库之后)。
它为Backbone.Collection对象提供了一种名为merge
的方法。它不是完全重置现有集合(如fetch
那样),而是将服务器响应与现有集合进行比较并合并它们的差异。
- 它增加模型在响应中,但不在现有的集合中。
- 它删除在现有集合中但未在响应中的模型。
- 最后,它更新在响应中的现有集合AND中找到的模型的属性。
为添加,删除和更新模型而触发所有预期事件。
的选项散列接受success
和error
回调将被传递(collection, response)
作为参数,它提供了一个名为即无论成功或错误(大多为轮询场景有用)执行complete
第三回调选项。
它会触发称为“合并:成功”和“合并:错误”的事件。
这里是扩展:
// Backbone Collection Extensions
// ---------------
// Extend the Collection type with a "merge" method to update a collection
// of models without doing a full reset.
Backbone.Collection.prototype.merge = function(callbacks) {
// Make a new collection of the type of the parameter
// collection.
var me = this;
var newCollection = new me.constructor(me.models, me.options);
this.success = function() { };
this.error = function() { };
this.complete = function() { };
// Set up any callbacks that were provided
if(callbacks != undefined) {
if(callbacks.success != undefined) {
me.success = callbacks.success;
}
if(callbacks.error != undefined) {
me.error = callbacks.error;
}
if(callbacks.complete != undefined) {
me.complete = callbacks.complete;
}
}
// Assign it the model and url of collection.
newCollection.url = me.url;
newCollection.model = me.model;
// Call fetch on the new collection.
return newCollection.fetch({
success: function(model, response) {
// Calc the deltas between the new and original collections.
var modelIds = me.getIdsOfModels(me.models);
var newModelIds = me.getIdsOfModels(newCollection.models);
// If an activity is found in the new collection that isn't in
// the existing one, then add it to the existing collection.
_(newCollection.models).each(function(activity) {
if (_.indexOf(modelIds, activity.id) == -1) {
me.add(activity);
}
}, me);
// If an activity in the existing collection isn't found in the
// new one, remove it from the existing collection.
var modelsToBeRemoved = new Array();
_(me.models).each(function(activity) {
if (_.indexOf(newModelIds, activity.id) == -1) {
modelsToBeRemoved.push(activity);
}
}, me);
if(modelsToBeRemoved.length > 0) {
for(var i in modelsToBeRemoved) {
me.remove(modelsToBeRemoved[i]);
}
}
// If an activity in the existing collection is found in the
// new one, update the existing collection.
_(me.models).each(function(activity) {
if (_.indexOf(newModelIds, activity.id) != -1) {
activity.set(newCollection.get(activity.id));
}
}, me);
me.trigger("merge:success");
me.success(model, response);
me.complete();
},
error: function(model, response) {
me.trigger("merge:error");
me.error(model, response);
me.complete();
}
});
};
Backbone.Collection.prototype.getIdsOfModels = function(models) {
return _(models).map(function(model) { return model.id; });
};
简单的使用场景:
var MyCollection = Backbone.Collection.extend({
...
});
var collection = new MyCollection();
collection.merge();
错误处理应用场景:
var MyCollection = Backbone.Collection.extend({
...
});
var collection = new MyCollection();
var jqXHR = collection.merge({
success: function(model, response) {
console.log("Merge succeeded...");
},
error: function(model, response) {
console.log("Merge failed...");
handleError(response);
},
complete: function() {
console.log("Merge attempt complete...");
}
});
function handleError(jqXHR) {
console.log(jqXHR.statusText);
// Direct the user to the login page if the session expires
if(jqXHR.statusText == 'Unauthorized') {
window.location.href = "/login";
}
};
的最佳解决方案。我正试图在collection.parse方法中完成此操作,并且无处可去。我真的希望这种行为被添加到骨干API。无论如何,这是我的TODO项目更新现有模型的实现。 '_(collection.models)。每个(功能(活性){ \t \t \t \t \t \t如果(newModelIds.indexOf(activity.id)!= - 1){ \t \t \t \t \t \t \t活性。集(newCollection.get(activity.id)); \t \t \t \t \t \t} \t \t \t \t那么);' – 2012-07-24 02:48:08