Backbone.Collection.merge([options])
在 @Jeb 的回答基础上,我将此行为封装成了一个 Backbone 扩展,您可以复制并粘贴到 .js 文件中,并在页面中包含它(在包含 Backbone 库本身之后)。
它提供了一个名为 merge
的方法,用于 Backbone.Collection 对象。与 fetch
不同,它不完全重置现有的集合,而是比较服务器响应和现有集合之间的差异进行合并。
- 它会向现有集合中添加在响应中出现但不存在于现有集合中的模型。
- 它会从现有集合中删除响应中没有的模型。
- 最后,它会更新现有集合中且在响应中也存在的模型的属性。
所有预期的事件都将被触发,用于添加、删除和更新模型。
选项哈希包含 success
和 error
回调函数,这些函数将作为参数传递给 (collection, response)
,并提供了第三个回调选项 complete
,无论成功还是失败都将执行它(对于轮询场景非常有帮助)。
它会触发名为 "merge:success" 和 "merge:error" 的事件。
下面是扩展内容:
Backbone.Collection.prototype.merge = function(callbacks) {
var me = this;
var newCollection = new me.constructor(me.models, me.options);
this.success = function() { };
this.error = function() { };
this.complete = function() { };
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;
}
}
newCollection.url = me.url;
newCollection.model = me.model;
return newCollection.fetch({
success: function(model, response) {
var modelIds = me.getIdsOfModels(me.models);
var newModelIds = me.getIdsOfModels(newCollection.models);
_(newCollection.models).each(function(activity) {
if (_.indexOf(modelIds, activity.id) == -1) {
me.add(activity);
}
}, me);
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]);
}
}
_(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);
if(jqXHR.statusText == 'Unauthorized') {
window.location.href = "/login";
}
};