"如何"在Backbone.js中保存整个集合 - Backbone.sync或jQuery.ajax?

PhD*_*PhD 81 ajax jquery backbone.js

我很清楚它可以完成,我已经看了很多地方(包括:保存整个集合的最佳实践?).但是我仍然不清楚它是用代码写的"究竟是怎么样的"?(这篇文章用英文解释.有一个特定于javascript的解释很棒:)

假设我有一组模型 - 模型本身可能有嵌套集合.我已经覆盖了父集合的toJSON()方法,我得到了一个有效的JSON对象.我希望"保存"整个集合(相应的JSON),但是主干似乎没有内置该功能.

var MyCollection = Backbone.Collection.extend({
model:MyModel,

//something to save?
save: function() {
   //what to write here?
 }

});
Run Code Online (Sandbox Code Playgroud)

我知道你要说的某个地方:

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?
 */
}
Run Code Online (Sandbox Code Playgroud)

一旦"查看"完成处理,它就负责告诉集合在服务器上"保存"自己(能够处理批量更新/创建请求).

出现的问题:

  1. 如何/在代码中写什么"将它们连在一起"?
  2. 回调的"正确"位置是什么以及如何指定"成功/错误"回调?我的意思是语法上的?我不清楚在骨干网中注册回调的语法......

如果它确实是一个棘手的工作,那么我们可以在视图中调用jQuery.ajax并传递this.successMethodthis.errorMethod作为成功/错误回调?? 它会起作用吗?

我需要与骨干的思维方式保持同步 - 我知道我肯定错过了一些东西,同步整个系列.

bra*_*ing 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
 }

});
Run Code Online (Sandbox Code Playgroud)

  • 我查看了源代码,似乎Collections**没有**有一个保存方法,所以覆盖不应该是一个问题(如果它确实有一个保存方法世界将是一个很容易:) (3认同)
  • 同意 - 非常优雅.但是,我遇到了这个解决方案的问题:我的包装器模型总是新的,因此当我save()它总是一个POST.我已经检索了我的数据,所以当我保存()它应该是一个PUT.我想我可以硬编码isNew()= false,或设置一个假ID,但这似乎不是一个优雅的解决方案.你有什么建议吗? (3认同)

hac*_*ack 25

一个非常简单的......

Backbone.Collection.prototype.save = function (options) {
    Backbone.sync("create", this, options);
};
Run Code Online (Sandbox Code Playgroud)

...将为您的馆藏提供一种保存方法.请记住,无论发生什么变化,都会将所有集合的模型发布到服务器.选项只是普通的jQuery ajax选项.

  • 似乎是对的.可能会添加`return Backbone.sync..`更多Backbonish. (4认同)

PhD*_*PhD 8

我最终只是采用了"保存"方法,并在其中调用了$ .ajax.它给了我更多的控制权,而不需要添加一个包装类,如@brandgonesurfing建议的那样(虽然我非常喜欢这个主意:)正如我所说的那样,因为我已经重写了collection.toJSON()方法,所以我所做的就是使用它在ajax电话中......

希望这可以帮助那些偶然发现它的人......

  • 你最好调用Backbone.ajax(无论如何它代理jQuery,但它使它更易于维护) (3认同)

car*_*iam 5

这实际上取决于客户端和服务器之间的合同.这是一个简化的CoffeeScript示例,其中PUT to /parent/:parent_id/childrenwith {"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
Run Code Online (Sandbox Code Playgroud)

这是一个非常简单的例子,你可以做更多......这实际上取决于执行save()时数据的状态,发送到服务器所需的状态以及服务器给出的内容背部.

如果您的服务器没有PUT [{child1},{child2],那么您的Backbone.sync线可以更改为response = Backbone.sync('update', @toJSON(), url: @url(), contentType: 'application/json').


inf*_*rno 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;
    }
});
Run Code Online (Sandbox Code Playgroud)

我认为关系模型更好,因为您可以更容易地配置它们,并且您可以使用 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'
            }
        }
    ]
});
Run Code Online (Sandbox Code Playgroud)

如果您不发送其他数据,则可以同步集合本身.在这种情况下,您必须为集合(或集合原型)添加一个save方法:

var Occupants = Backbone.Collection.extend({
    url: "/concrete-house/occupants",
    model: Person,
    save: function (options) {
        this.sync("update", this, options);
    }
});
Run Code Online (Sandbox Code Playgroud)