我很清楚它可以完成,我看了很多地方(包括:Best practice for saving an entire collection?)。但我仍然不清楚它在代码中写的“究竟是怎么样的”? (这篇文章用英文解释。有一个特定于javascript的解释很棒:)。
假设我有一组模型 - 模型本身可能有嵌套集合。我已经覆盖了父集合的toJSON()方法,我得到了一个有效的JSON对象。我希望“保存”整个集合(相应的JSON),但是主干似乎没有内置该功能。
var MyCollection = Backbone.Collection.extend({
model:MyModel,
//something to save?
save: function() {
//what to write here?
}
});
我知道你要说的某个地方:
Backbone.sync = function(method, model, options){
/*
* What goes in here?? If at all anything needs to be done?
* Where to declare this in the program? And how is it called?
*/
}
一旦'view'完成处理,它就负责告诉集合在服务器上“保存”它自己(能够处理批量更新/创建请求)。
出现的问题:
如果它确实是一个棘手的工作,那么我们可以在一个视图中调用jQuery.ajax并传递this.successMethod
或this.errorMethod
作为成功/错误回调??它会起作用吗?
我需要与骨干的思维方式保持同步 - 我知道我肯定错过了w.r.t.,同步整个系列。
答案 0 :(得分:64)
我的想法是不要覆盖Backbone.Collection上的save方法上的方法,而是将该集合包装在另一个Backbone.Model中并覆盖其上的toJSON方法。然后Backbone.js会将模型视为单一资源,而且你不必破解backone认为过多的方式。
请注意,Backbone.Collection具有toJSON方法,因此您的大部分工作都是为您完成的。您只需将包装器Backbone.Model的toJSON方法代理到Backbone.collection。
var MyCollectionWrapper = Backbone.Model.extend({
url: "/bulkupload",
//something to save?
toJSON: function() {
return this.model.toJSON(); // where model is the collection class YOU defined above
}
});
答案 1 :(得分:25)
非常简单......
Backbone.Collection.prototype.save = function (options) {
Backbone.sync("create", this, options);
};
...将为您的馆藏提供一种保存方法。请记住,无论发生什么变化,都会将所有集合的模型发布到服务器。选项只是普通的jQuery ajax选项。
答案 2 :(得分:8)
我最终只是采用了'save'方法,并在其中调用了$ .ajax。它给了我更多的控制权,而不需要添加一个包装类,如@brandgonesurfing建议的那样(虽然我非常喜欢这个主意:)正如我所说的那样,因为我已经重写了collection.toJSON()方法,所以我所做的就是使用它在ajax电话中......
希望这可以帮助那些偶然发现它的人......
答案 3 :(得分:5)
这实际上取决于客户端和服务器之间的合同。这是一个简化的CoffeeScript示例,其中/parent/:parent_id/children
与{"children":[{child1},{child2}]}
的PUT将用PUT中的内容替换父项的子项并返回{"children":[{child1},{child2}]}
:
class ChildElementCollection extends Backbone.Collection
model: Backbone.Model
initialize: ->
@bind 'add', (model) -> model.set('parent_id', @parent.id)
url: -> "#{@parent.url()}/children" # let's say that @parent.url() == '/parent/1'
save: ->
response = Backbone.sync('update', @, url: @url(), contentType: 'application/json', data: JSON.stringify(children: @toJSON()))
response.done (models) => @reset models.children
return response
这是一个非常简单的例子,你可以做更多......它实际上取决于你的数据在执行save()时的状态,它需要进入服务器的状态,以及服务器回馈。
如果您的服务器的PUT为[{child1},{child2]
,那么您的Backbone.sync行可能会更改为response = Backbone.sync('update', @toJSON(), url: @url(), contentType: 'application/json')
。
答案 4 :(得分:5)
答案取决于您想要对服务器端的集合做什么。
如果您必须使用帖子发送其他数据,则可能需要包装模型或关系模型。
使用包装模型,您始终必须编写自己的解析方法:
var Occupants = Backbone.Collection.extend({
model: Person
});
var House = Backbone.Model.extend({
url: function (){
return "/house/"+this.id;
},
parse: function(response){
response.occupants = new Occupants(response.occupants)
return response;
}
});
我认为Relational models 更好,因为您可以更轻松地配置,并且您可以使用includeInJSON选项来规范哪些属性要放入你发送到休息服务的json。
var House = Backbone.RelationalModel.extend({
url: function (){
return "/house/"+this.id;
},
relations: [
{
type: Backbone.HasMany,
key: 'occupants',
relatedModel: Person,
includeInJSON: ["id"],
reverseRelation: {
key: 'livesIn'
}
}
]
});
如果您不发送其他数据,则可以自行同步收藏。在这种情况下,您必须为集合(或集合原型)添加保存方法:
var Occupants = Backbone.Collection.extend({
url: "/concrete-house/occupants",
model: Person,
save: function (options) {
this.sync("update", this, options);
}
});
答案 5 :(得分:3)
我也很惊讶Backbone收藏没有内置保存。这是我在我的骨干系列上做的事情。我绝对不想遍历集合中的每个模型并独立保存。另外,我在后端使用Node使用Backbone,所以我覆盖了本地Backbone.sync
以保存到我的小项目中的平面文件 - 但代码应该是相同的:
save: function(){
Backbone.sync('save', this, {
success: function(){
console.log('users saved!');
}
});
}
答案 6 :(得分:3)
旧线程我知道,我最终做的是以下内容:
Backbone.Collection.prototype.save = function (options) {
// create a tmp collection, with the changed models, and the url
var tmpCollection = new Backbone.Collection( this.changed() );
tmpCollection.url = this.url;
// sync
Backbone.sync("create", tmpCollection, options);
};
Backbone.Collection.prototype.changed = function (options) {
// return only the changed models.
return this.models.filter( function(m){
return m.hasChanged()
});
};
// and sync the diffs.
self.userCollection.save();
漂亮的紧张前行:)
答案 7 :(得分:2)
这是一个简单的例子:
var Books = Backbone.Collection.extend({
model: Book,
url: function() {
return '/books/';
},
save: function(){
Backbone.sync('create', this, {
success: function() {
console.log('Saved!');
}
});
}
});
当您在集合上调用save()方法时,它会向定义的URL发送PUT方法请求。
答案 8 :(得分:1)
我会尝试类似的事情:
var CollectionSync = function(method, model, [options]) {
// do similar things to Backbone.sync
}
var MyCollection = Backbone.Collection.extend({
sync: CollectionSync,
model: MyModel,
getChanged: function() {
// return a list of models that have changed by checking hasChanged()
},
save: function(attributes, options) {
// do similar things as Model.save
}
});
答案 9 :(得分:1)
接受的答案非常好,但我可以更进一步,为您提供代码,确保为您的侦听器触发正确的事件,同时还允许您传入选项ajax事件回调:
print(service.translations().list(source='zh',
target='en',
q=['上海熙缘节能环保科技服务有限公司',
'广东宏德科技物业有限公司']).execute())
if __name__ == '__main__':
main()
答案 10 :(得分:0)
对于2017年仍在使用backbone.js的任何人,接受的答案都无效。
在实例化模型包装器时,尝试删除包装器模型中的toJSON()重写并在集合上调用toJSON。
new ModelWrapper(Collection.toJSON());