nam*_*rot 6 javascript backbone.js
我想我有一个非常简单的问题,很难说出来,因此很难找到解决方案.建立:
当我获取PathCollection时
paths = new PathCollection()
paths.fetch()
Run Code Online (Sandbox Code Playgroud)
很明显,Paths实例化了.但是,我错过了我可以允许Path从属性哈希实例化其子模型的地方.我不能真正使用解析,对吧?基本上我正在寻找模型的入口点,当它实例化并设置属性时.我觉得必须有一些惯例.
jmk*_*142 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.
Run Code Online (Sandbox Code Playgroud)
这是最简单的方法,当您处理不需要定义的一次性模型和集合时,它可以很好地工作.虽然您可以在某些方法(例如视图方法)中轻松生成这些模型,但在使用它之前构造此对象.
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;
}
});
Run Code Online (Sandbox Code Playgroud)
现在您的子集合可以被提取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'}
]
}
Run Code Online (Sandbox Code Playgroud)
使用默认的parse()Backbone将吞噬它并将数据(不是集合)的数组()分配给你的路径模型属性'nodes'和'edge'.所以我们要确保我们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;
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用自定义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);
}
Run Code Online (Sandbox Code Playgroud)
因此,如果我们已经有一个属性并且它是一个集合,那么我们就是reset()这样.如果我们有一个属性但它不是一个集合,我们实例化它.在将子数据的JSON数组传递给原型之前,确保正确地将其转换为集合非常重要set().Backbone,不会将JSON数组解释为集合,并且您只能获得一个直接数组.
所以在一个坚果壳中,你有很多关于如何去做的选择.同样,目前我赞成混合使用initialize()当我知道某些东西将始终具有那些子模型/集合时以及parse()当情况仅调用可能的嵌套数据时fetch().
关于你的这个问题......(哦,是的,有一个问题)
您可以允许Path以各种方式从哈希实例化子模型.我刚给你4.如果你想要你可以使用解析,如果你知道你将成为fetch()路径模型或者甚至是pathCollection ... pathCollection.fetch({parse:true})是否有约定?也许不是.我喜欢使用各种方式的组合,这取决于我认为我将使用模型/集合的上下文.
我很乐意讨论其中的一些做法以及它们是好还是坏.它们只是我在Stack上遇到的许多解决方案,并融入了我自己的工作习惯中,它们似乎对我来说很好.:-)
给自己一杯咖啡,拍拍背面,这是一个很长的阅读.