转换/初始化Backbone模型的子模型

时间:2012-09-10 10:55:04

标签: javascript backbone.js

我认为我有一个非常简单的问题,很难说出来,因此很难找到解决方案。设置:

  • PathCollection是路径的Backbone.Collection
  • Path是一个Backbone.Model,它包含NodeCollection(Backbone.Collection)和EdgeCollection(Backbone.Collection)。

当我获取PathCollection

paths = new PathCollection()
paths.fetch()
显然,Paths被实例化了。但是,我错过了我可以允许Path从属性哈希实例化其子模型的地方。我不能真正使用解析,对吧?基本上我正在寻找模型的入口点,当它实例化并设置属性时。我觉得必须有一些约定。

1 个答案:

答案 0 :(得分:25)

所以我写了几个关于使用parse()set()来实例化和填充子模型和子集合(嵌套数据)的答案。但是,我还没有看到一个非常全面的答案,它巩固了我所看到的一些实践。当我写很多东西时,我倾向于絮絮叨叨,所以我可能会稍微离题,但这对于遇到类似问题的人来说可能是有用的。

有几种方法可以做到这一点。使用parse()是一个。操纵set()是另一个。在initialize()中实例化这些是另一个。在Path模型之外完成所有操作(例如path = new Path(); path.nodes = new NodeCollection();等)。

第二个考虑是这个。您希望节点和边集合是模型属性吗?还是模型属性?

哦,有这么多选择。很多自由,但有时候(让我们感到沮丧)这使得确定“正确的方式”变得更加困难。

由于经常会出现这种情况,我会做一个很长的帖子并逐一完成。所以请耐心等待我继续更新这个答案。

在模特之外做 - 简单直接

当您只需要在特定模型或集合上添加嵌套模型和集合时,这通常是一种简单的方法。

path = new PathModel();

path.nodes = new NodeCollection();
path.edge = new EdgeCollection();

// Continue to set up the nested data URL, etc.

这是最简单的方法,当您处理不需要定义的一次性模型和集合时,效果很好。虽然您可以在某些方法(例如视图方法)中轻松生成这些模型,但在使用它之前构造此对象。

在每个模型中使用initialize()子模型/集合

如果您知道某个模型的每个实例都将始终具有子模型或子集合,则设置最简单的方法是使用initialize()函数。

例如,选择Path模型:

Path = Backbone.Model.extend({
    initialize: function() {
        this.nodes = new NodeCollection();
        this.paths = new PathCollection();

        // Maybe assign a proper url in relation to this Path model
        // You might even set up a change:id listener to set the url when this
        // model gets an id, assuming it doesn't have one at start.
        this.nodes.url = this.id ? 'path/' + this.id + '/nodes' : undefined;
        this.paths.url = this.id ? 'path/' + this.id + '/paths' : undefined;
    }
});

现在可以像path.nodes.fetch()一样提取您的子集合,它将路由到正确的URL。容易腻。

使用parse()实例化和设置子数据

如果您不想假设每个模型都有节点和边集合,那么它会变得有点棘手。也许只有在fetch()发回这些数据时才需要嵌套模型/集合。这种情况下使用parse()可以派上用场。

parse()的问题是它需要任何json服务器响应,并且可以在将其传递给模型set()函数之前正确命名并处理它。因此,我们可以检查是否包含模型或集合原始数据,并在将响应减少到父模型属性之前处理它。

例如,也许从我们的服务器获得此响应:

// Path model JSON example with nested collections JSON arrays
{
    'name':'orange site',
    'url':'orange.com',
    'nodes':[
        {'id':'1', 'nodeColor':'red'},
        {'id':'2', 'nodeColor':'white'},
        {'id':'3', 'nodeColor':'blue'}
    ],
    'edge':[
        {'id':'1', 'location':'north'},
        {'id':'1', 'location':'south'},
        {'id':'1', 'location':'east'}
    ]
}

使用默认的parse() Backbone将吞噬它并使用数组(不是集合)分配路径模型属性“nodes”和“edge”。所以我们要确保我们的{ {1}}适当地处理此事。

parse()

您还可以使用自定义parse: function(response) { // Check if response includes some nested collection data... our case 'nodes' if (_.has(response, 'nodes')){ // Check if this model has a property called nodes if (!_.has(this, 'nodes')) { // It does not... // So instantiate a collection and pass in raw data this.nodes = new NodeCollection(response.nodes); } else { // It does, so just reset the collection this.nodes.reset(response.nodes); } // Assuming the fetch gets this model id this.nodes.url = 'path/' + response.id + '/nodes'; // Set model relative URL // Delete the nodes so it doesn't clutter our model attributes delete response.nodes; } // Same for edge... return response; } 来处理子数据。经过多次更好的交流,操纵set()或在set()中进行操作后,我决定更多地使用parse()。但我对其他人的想法持开放态度。

使用parse()处理您的子数据

虽然set()依赖于获取数据或使用选项parse()将数据传递到集合,但有些人发现更改parse:true函数是优先的。同样,我不确定是否有正确的选择,但这是如何工作的。

set()

因此,如果我们已经有一个属性并且它是一个集合,那么我们set: function(attributes, options) { // If we pass in nodes collection JSON array and this model has a nodes attribute // Assume we already set it as a collection if (_.has(attributes, 'nodes') && this.get("nodes")) { this.get('nodes').reset(attributes.nodes); delete attributes.nodes; } else if (_.has(attributes, 'nodes') && !this.get('nodes')) { this.set('nodes', new NodeCollection(attributes.nodes)); delete attributes.nodes; } return Backbone.Model.prototype.set.call(this, attributes, options); } 。如果我们有一个属性但它不是一个集合,我们实例化它。在将子数据的JSON数组传递给原型reset()之前,确保正确地将其转换为集合非常重要。 Backbone,不会将JSON数组解释为集合,您只能获得一个直接数组。

所以在坚果壳中,你有很多关于如何去做的选择。同样,目前我赞成混合使用set()当我知道某些内容将始终具有这些子模型/集合时,initialize()当情况仅调用parse()调用上可能的嵌套数据时。

关于你的那个问题......(哦,是的,有一个问题)

您可以允许Path以各种方式从哈希实例化子模型。我刚给你4.如果你想要,你可以使用解析,如果你知道你将成为fetch()路径模型或者甚至是pathCollection ...... fetch()是否有约定?也许不是。我喜欢使用各种方式的组合,这取决于我认为我将使用模型/集合的上下文。

我很乐意讨论其中的一些做法以及它们的好坏。它们只是我在Stack上遇到的许多解决方案,并融入了我自己的工作习惯中,它们似乎对我来说很好。 : - )

给自己喝杯咖啡,拍拍背面,这是一个很长的阅读时间。