Backbone.js中的嵌套模型,如何处理

Ros*_*oss 116 javascript backbone.js backbone-model

我从服务器提供了以下JSON.有了这个,我想创建一个嵌套模型的模型.我不确定实现这一目标的方法.

//json
[{
    name : "example",
    layout : {
        x : 100,
        y : 100,
    }
}]
Run Code Online (Sandbox Code Playgroud)

我希望这些转换为两个嵌套的骨干模型,具有以下结构:

// structure
Image
    Layout
...
Run Code Online (Sandbox Code Playgroud)

所以我定义了Layout模型,如下所示:

var Layout = Backbone.Model.extend({});
Run Code Online (Sandbox Code Playgroud)

但是下面两种(如果有的话)技术中的哪一种应该用于定义Image模型?A或B下面?

一个

var Image = Backbone.Model.extend({
    initialize: function() {
        this.set({ 'layout' : new Layout(this.get('layout')) })
    }
});
Run Code Online (Sandbox Code Playgroud)

或者, B

var Image = Backbone.Model.extend({
    initialize: function() {
        this.layout = new Layout( this.get('layout') );
    }
});
Run Code Online (Sandbox Code Playgroud)

ryc*_*ung 98

在编写Backbone应用程序时,我遇到了同样的问题.必须处理嵌入/嵌套模型.我做了一些调整,我认为这是一个非常优雅的解决方案.

是的,您可以修改parse方法来更改对象中的属性,但所有这些实际上都是非常难以维护的代码IMO,并且感觉更像是一个hack而不是解决方案.

以下是我为您的示例建议的内容:

首先像这样定义您的布局模型.

var layoutModel = Backbone.Model.extend({});
Run Code Online (Sandbox Code Playgroud)

那么这是你的形象型号:

var imageModel = Backbone.Model.extend({

    model: {
        layout: layoutModel,
    },

    parse: function(response){
        for(var key in this.model)
        {
            var embeddedClass = this.model[key];
            var embeddedData = response[key];
            response[key] = new embeddedClass(embeddedData, {parse:true});
        }
        return response;
    }
});
Run Code Online (Sandbox Code Playgroud)

请注意,我没有篡改模型本身,只是从parse方法传回所需的对象.

当您从服务器读取时,这应该确保嵌套模型的结构.现在,您会注意到此处实际上没有处理保存或设置,因为我觉得使用正确的模型显式设置嵌套模型是有意义的.

像这样:

image.set({layout : new Layout({x: 100, y: 100})})
Run Code Online (Sandbox Code Playgroud)

另请注意,您实际上是通过调用以下方法在嵌套模型中调用parse方法:

new embeddedClass(embeddedData, {parse:true});
Run Code Online (Sandbox Code Playgroud)

您可以根据model需要在字段中定义任意数量的嵌套模型.

当然,如果你想在自己的表中保存嵌套模型.这还不够.但是在读取和保存整个对象的情况下,这个解决方案应该足够了.

  • 这很好..应该是接受的答案,因为它比其他方法更清洁.我建议的唯一建议是将扩展Backbone.Model的类的第一个字母大写以便于阅读..即ImageModel和LayoutModel (4认同)
  • 太好了!我建议将其添加到`Backbone.Model.prototype.parse`函数中.然后,您的模型所要做的就是定义子模型对象类型(在"model"属性中). (2认同)

Eri*_* Hu 16

我发布此代码作为Peter Lyon关于重新定义解析的建议的一个例子.我有同样的问题,这对我有用(使用Rails后端).此代码以Coffeescript编写.我为那些不熟悉它的人做了一些明确的事情.

class AppName.Collections.PostsCollection extends Backbone.Collection
  model: AppName.Models.Post

  url: '/posts'

  ...

  # parse: redefined to allow for nested models
  parse: (response) ->  # function definition
     # convert each comment attribute into a CommentsCollection
    if _.isArray response
      _.each response, (obj) ->
        obj.comments = new AppName.Collections.CommentsCollection obj.comments
    else
      response.comments = new AppName.Collections.CommentsCollection response.comments

    return response
Run Code Online (Sandbox Code Playgroud)

或者,在JS中

parse: function(response) {
  if (_.isArray(response)) {
    return _.each(response, function(obj) {
      return obj.comments = new AppName.Collections.CommentsCollection(obj.comments);
    });
  } else {
    response.comments = new AppName.Collections.CommentsCollection(response.comments);
  }
  return response;
};
Run Code Online (Sandbox Code Playgroud)

  • 如果问题是真正的JS,那么答案也应该如此. (16认同)
  • 很高兴能在真正的JS中得到答案 (11认同)
  • 很高兴有coffeescript版本,谢谢.对于其他人,请尝试http://js2coffee.org/ (6认同)

Pet*_*ons 11

我不确定Backbone本身是否有推荐的方法来做到这一点.Layout对象在后端数据库中是否有自己的ID和记录?如果是这样,你可以像你一样制作自己的模型.如果没有,您可以将其保留为嵌套文档,只需确保在saveparse方法中正确地将其转换为JSON .如果您最终采取这样的方法,我认为您的A示例与骨干更加一致,因为set将正确更新attributes,但我再次确定Backbone默认情况下对嵌套模型的作用.您可能需要一些自定义代码来处理这个问题.


Jay*_*ani 11

使用Backbone.AssociatedModel骨干网的协会:

    var Layout = Backbone.AssociatedModel.extend({
        defaults : {
            x : 0,
            y : 0
        }
    });
    var Image = Backbone.AssociatedModel.extend({
        relations : [
            type: Backbone.One,
            key : 'layout',
            relatedModel : Layout          
        ],
        defaults : {
            name : '',
            layout : null
        }
    });
Run Code Online (Sandbox Code Playgroud)


phi*_*reo 8

如果你想保持简单,我会选择选项B.

另一个好的选择是使用Backbone-Relational.你只需定义如下内容:

var Image = Backbone.Model.extend({
    relations: [
        {
            type: Backbone.HasOne,
            key: 'layout',
            relatedModel: 'Layout'
        }
    ]
});
Run Code Online (Sandbox Code Playgroud)


Mar*_*ark 6

我使用Backbone DeepModel插件来嵌套模型和属性.

https://github.com/powmedia/backbone-deep-model

您可以绑定以更改事件的n级深度.例如: model.on('change:example.nestedmodel.attribute', this.myFunction);


Dan*_*Fox 5

CoffeeScript版本的rycfung的美丽答案:

class ImageModel extends Backbone.Model
  model: {
      layout: LayoutModel
  }

  parse: (response) =>
    for propName,propModel of @model
      response[propName] = new propModel( response[propName], {parse:true, parentModel:this} )

    return response
Run Code Online (Sandbox Code Playgroud)

那不是很好吗?;)

  • 我不会在我的JavaScript中加糖:) (11认同)