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需要在字段中定义任意数量的嵌套模型.
当然,如果你想在自己的表中保存嵌套模型.这还不够.但是在读取和保存整个对象的情况下,这个解决方案应该足够了.
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)
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)
Pet*_*ons 11
我不确定Backbone本身是否有推荐的方法来做到这一点.Layout对象在后端数据库中是否有自己的ID和记录?如果是这样,你可以像你一样制作自己的模型.如果没有,您可以将其保留为嵌套文档,只需确保在save和parse方法中正确地将其转换为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)
如果你想保持简单,我会选择选项B.
另一个好的选择是使用Backbone-Relational.你只需定义如下内容:
var Image = Backbone.Model.extend({
relations: [
{
type: Backbone.HasOne,
key: 'layout',
relatedModel: 'Layout'
}
]
});
Run Code Online (Sandbox Code Playgroud)
我使用Backbone DeepModel插件来嵌套模型和属性.
https://github.com/powmedia/backbone-deep-model
您可以绑定以更改事件的n级深度.例如:
model.on('change:example.nestedmodel.attribute', this.myFunction);
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)
那不是很好吗?;)