“如何”在 Backbone.js 中保存整个集合 - Backbone.sync 或 jQuery.ajax?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6879138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"How" to save an entire collection in Backbone.js - Backbone.sync or jQuery.ajax?
提问by PhD
I am well aware it can be done and I've looked at quite a few places (including: Best practice for saving an entire collection?). But I'm still not clear "exactly how" is it written in code? (the post explains it in English. It'd be great to have a javascript specific explanation :)
我很清楚这是可以做到的,而且我看过很多地方(包括:保存整个集合的最佳实践?)。但我仍然不清楚它“究竟如何”用代码编写?(这篇文章用英语解释了它。有一个 javascript 特定的解释会很棒:)
Say I have a collection of models - the models themselves may have nested collections. I have overridden the toJSON() method of the parent collection and I am getting a valid JSON object. I wish to "save" the entire collection (corresponding JSON), but backbone doesn't seem to come in-built with that functionality.
假设我有一个模型集合 - 模型本身可能有嵌套集合。我已经覆盖了父集合的 toJSON() 方法,并且我得到了一个有效的 JSON 对象。我希望“保存”整个集合(对应的 JSON),但主干似乎没有内置该功能。
var MyCollection = Backbone.Collection.extend({
model:MyModel,
//something to save?
save: function() {
//what to write here?
}
});
I know somewhere you have to say:
我知道你必须在某处说:
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?
*/
}
Once the 'view' is done with the processing it is responsible for telling the collection to "save" itself on the server (capable of handling a bulk update/create request).
一旦“视图”完成处理,它负责告诉集合将自身“保存”在服务器上(能够处理批量更新/创建请求)。
Questions that arise:
出现的问题:
- How/what to write in code to "wire it all together"?
- What is the 'right' location of the callbacks and how to specify a "success/error" callback? I mean syntactically?I'm not clear of the syntax of registering callbacks in backbone...
- 如何/在代码中编写什么来“将它们连接在一起”?
- 回调的“正确”位置是什么以及如何指定“成功/错误”回调?我的意思是在语法上?我不清楚在主干中注册回调的语法......
If it is indeed a tricky job then can we call jQuery.ajax within a view and pass the this.successMethod
or this.errorMethod
as success/error callbacks?? Will it work?
如果这确实是一项棘手的工作,那么我们可以在视图中调用 jQuery.ajax 并将this.successMethod
或this.errorMethod
作为成功/错误回调传递吗?它会起作用吗?
I need to get in sync with backbone's way of thinking - I know I'm definitely missing something w.r.t., syncing of entire collections.
我需要与主干的思维方式保持同步——我知道我肯定错过了一些东西,同步整个集合。
采纳答案by bradgonesurfing
My immediate thought is not to override the method on save method on Backbone.Collection but wrap the collection in another Backbone.Model and override the toJSON method on that. Then Backbone.js will treat the model as a single resource and you don't have to hack the way backone thinks too much.
我的直接想法不是在 Backbone.Collection 上覆盖 save 方法上的方法,而是将集合包装在另一个 Backbone.Model 中并覆盖其上的 toJSON 方法。然后 Backbone.js 会将模型视为单一资源,您不必像 backone 那样想太多。
Note that Backbone.Collection has a toJSON method so most of your work is done for you. You just have to proxy the toJSON method of your wrapper Backbone.Model to the Backbone.collection.
请注意,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
}
});
回答by hacklikecrack
A very simple...
一个非常简单的...
Backbone.Collection.prototype.save = function (options) {
Backbone.sync("create", this, options);
};
...will give your collections a save method. Bear in mind this will always post all the collection's models to the server regardless of what has changed. options are just normal jQuery ajax options.
...会给你的收藏一个保存方法。请记住,无论发生了什么变化,这都会始终将所有集合的模型发布到服务器。选项只是普通的 jQuery ajax 选项。
回答by PhD
I ended up just having a 'save' like method and called $.ajax within it. It gave me more control over it without the need to add a wrapper class as @brandgonesurfing suggested (although I absolutely love the idea :) As mentioned since I already had the collection.toJSON() method overridden all I landed up doing was using it in the ajax call...
我最终只有一个类似“保存”的方法,并在其中调用了 $.ajax。它让我可以更好地控制它,而无需像@brandgonesurfing 建议的那样添加包装类(尽管我非常喜欢这个想法:) 如前所述,因为我已经覆盖了 collection.toJSON() 方法,我所做的只是使用它在 ajax 调用中...
Hope this helps someone who stumbles upon it...
希望这可以帮助那些偶然发现它的人......
回答by carpeliam
This really depends on what the contract is between the client and server. Here's a simplified CoffeeScript example where a PUT to /parent/:parent_id/children
with {"children":[{child1},{child2}]}
will replace a parent's children with what's in the PUT and return {"children":[{child1},{child2}]}
:
这实际上取决于客户端和服务器之间的合同。这是一个简化的 CoffeeScript 示例,其中 PUT to /parent/:parent_id/children
with{"children":[{child1},{child2}]}
将用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
This is a pretty simple example, you can do a lot more... it really depends on what state your data's in when save() is executed, what state it needs to be in to ship to the server, and what the server gives back.
这是一个非常简单的例子,你可以做更多......这实际上取决于执行 save() 时你的数据处于什么状态,它需要处于什么状态才能发送到服务器,以及服务器提供什么背部。
If your server is ok with a PUT of [{child1},{child2]
, then your Backbone.sync line could change to response = Backbone.sync('update', @toJSON(), url: @url(), contentType: 'application/json')
.
如果您的服务器在 PUT 上没有问题[{child1},{child2]
,那么您的 Backbone.sync 行可能会更改为response = Backbone.sync('update', @toJSON(), url: @url(), contentType: 'application/json')
。
回答by inf3rno
The answer depends on what you want to do with the collection on server side.
答案取决于您想对服务器端的集合做什么。
If you have to send additional datawith the post you might need a wrapper model or a relational model.
如果您必须随帖子发送其他数据,您可能需要一个包装模型或关系模型。
With the wrapper modelyou always have to write your own parsemethod:
使用包装器模型,您始终必须编写自己的解析方法:
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 modelsare better I think, because you can configure them easierand you can regulate with the includeInJSONoption which attributes to put into the json you send to your rest service.
我认为关系模型更好,因为您可以更轻松地配置它们,并且您可以使用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'
}
}
]
});
If you don't send additional data, you can sync the collection itself. You have to add a savemethod to your collection (or the collection prototype) in that case:
如果您不发送额外数据,您可以同步集合本身。在这种情况下,您必须向您的集合(或集合原型)添加一个save方法:
var Occupants = Backbone.Collection.extend({
url: "/concrete-house/occupants",
model: Person,
save: function (options) {
this.sync("update", this, options);
}
});
回答by Rene Weteling
Old thread i know, what i ended up doing is the following:
我知道旧线程,我最终做的是以下内容:
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();
Pretty straint foreward :)
向前相当紧张:)
回答by Mauvis Ledford
I was also surprised that Backbone collections don't have a built in save. Here's what I put on my backbone collection to do it. I definitely don't want to iterate through each model in the collection and save independently. Also, I am using Backbone on the backend using Node so am overridding the native Backbone.sync
to save to a flat file on my small project—but the code should pretty much be the same:
我也很惊讶 Backbone 集合没有内置保存。这是我在我的骨干收藏中所做的。我绝对不想遍历集合中的每个模型并独立保存。此外,我在后端使用 Node 使用 Backbone,因此我覆盖了本机Backbone.sync
以保存到我的小项目中的平面文件 - 但代码应该几乎相同:
save: function(){
Backbone.sync('save', this, {
success: function(){
console.log('users saved!');
}
});
}
回答by Gaurav Gupta
Here's a simple example:
这是一个简单的例子:
var Books = Backbone.Collection.extend({
model: Book,
url: function() {
return '/books/';
},
save: function(){
Backbone.sync('create', this, {
success: function() {
console.log('Saved!');
}
});
}
});
When you call the save() method on your collection, it will send a PUT method request to the defined URL.
当您对集合调用 save() 方法时,它将向定义的 URL 发送 PUT 方法请求。
回答by Throttlehead
The accepted answer is pretty good, but I can go one step further and give you code that will ensure the proper events are fired for your listeners while also allowing you to pass in option ajax event callbacks:
接受的答案非常好,但我可以更进一步,为您提供代码,以确保为您的侦听器触发正确的事件,同时还允许您传入选项 ajax 事件回调:
save: function( options ) {
var self = this;
var success = options.success;
var error = options.error;
var complete = options.complete;
options.success = function( response, status, xhr ) {
self.trigger('sync', self, response, options);
if (success) return success.apply(this, arguments);
};
options.error = function( response, status, xhr ) {
self.trigger('error', self, response, options);
if (error) return error.apply(this, arguments);
};
options.complete = function( response, status, xhr ) {
if (complete) return complete.apply(this, arguments);
}
Backbone.sync('create', this, options);
}
回答by philfreo
I would try something like:
我会尝试类似的东西:
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
}
});