我的webapp有一个复合结构,即每个Category集合可以包含单个Items和其他Categories的混合作为其行/节点/子节点(这里不确定正确的术语)。实际上,它比这更简单,因为每个集合都由一个模型Category表示,所以基本上每个Category集合都有Item模型和Category模型作为它的子项。
一般来说这是使用MVC实现此结构的可行方法吗?更具体地说,在Backbone.js中,集合是否可以拥有模型工厂(获取json并根据json的结构计算生成哪个模型)而不是静态模型属性?
答案 0 :(得分:5)
我假设您在JSON中收到的类别/项目列表看起来像这样......
{
'id': 1,
'name': 'My 1st Category',
'children': [
{
'id': 2,
'name': 'My 2nd Category',
'children': []
},
{
'id': 1,
'name': 'An Item',
'price': 109.99
}
]
}
Backbone.js没有开箱即用的支持集合中多个模型的东西,但它对你在集合中放置的模型类型也没有任何限制。
在集合定义中指定模型类型只做一件事,如果将原始JSON传递给集合而不是Backbone.Model
对象,它可以让Backbone知道要创建的模型类型。如果您将Item
模型添加到已包含少量Category
模型的集合中,Backbone将没有问题将其弹出到模型列表中;它不进行任何类型检查。
因此,考虑到这一点,您可以使用集合提供的所有内容,除非传递原始JSON;你需要自己处理。因此,您可以选择预先构建模型,将它们转换为Backbone.Model
个对象,或者创建一些可以为您解析的内容。
对于第二个选项,解析器,我建议将一个特殊变量传递给包含原始JSON的集合,然后在initialize
函数中处理它。这是一个例子:
var CategoryCollection = Backbone.Collection.extend({
initialize: function(m, models) {
_.each(models, function(model) {
var modelObject = null;
if (model.price !== undefined) {
modelObject = new Item(model);
} else {
modelObject = new Category(model);
}
this.add(modelObject);
}, this);
}
});
所以它有点hacky,但你根据它是否有一个特定字段(在我的例子中为price
)确定模型的类型,创建模型对象,然后将其添加到集合中。
然后你会这样称呼它:
var myCollection = new CategoryCollection([], myJSON);
请注意,您必须传递一个空数组作为第一个参数,因为您通常会将一组模型传递给集合。
稍后使用该集合时,您可以使用简单的Item
支票确定您是在处理Category
还是instanceof
:
_.each(myCollection.models, function(model) {
if (model instanceof Item) {
console.log("It's an Item! Price: ", model.get("price"));
} else {
console.log("It's a Category!");
}
});
答案 1 :(得分:1)
是的,你可以。我以前做过。我认为此链接可以帮助您:http://documentcloud.github.com/backbone/#Collection-model
以下是我用于项目的主要脚本之一:https://gist.github.com/b65893e0c2e3c46d3dc1
答案 2 :(得分:1)
通过覆盖检索和保存模型数据时骨干网内部使用的内置公共方法parse和toJSON,可以相当简单地实现。
首先,当您从数据库中检索模型时,您应该覆盖模型的parse
方法,以创建表示示例中给定项的模型。
然后在保存时,toJSON
方法用于将数据序列化回服务器可以理解的内容 - 您只需在每个项目的模型上调用toJSON
方法将其序列化为格式后端会认出来的。如果查看Backbone.sync
的代码,如果没有传递自定义数据,您将看到模型总是使用toJSON进行序列化。
如果您需要更详细的信息,请告诉我,但我相信您应该可以从这里获取信息!
答案 3 :(得分:1)
是的,您可以使用工厂方法模式在骨干集合中创建模型。假设@kpeel's answer中建议的数据结构,您可以定义
// Factory method
var CategoryOrItemFactory = function(data, options) {
if (data.children) {
return new Category(data, options);
} else {
return new Item(data, options);
}
};
// Model definitions
var Item = Backbone.Model.extend();
var Category = Backbone.Model.extend({
initialize: function() {
this.children = new Children(this.get("children"));
}
});
var Children = Backbone.Collection.extend({
model: CategoryOrItemFactory
});
然后,您将创建根项(类别)并创建完整的数据结构:
// create the root item
var rootItem = new Category(rawData);
访问类别的子项children
属性,例如
rootItem.children.get(2).get("name");