我的webapp具有复合结构,即每个类别集合可以包含单个项目和其他类别的混合作为其行/节点/子项(在此不确定正确的术语).实际上,它比这个简单一点,因为每个集合都是由一个模型“类别”表示的,所以基本上每个类别集合都有Item模型和Category模型作为其子项.
一般来说,这是使用MVC实现这种结构的一种可取的方法吗?更具体地说,在Backbone.js中,一个集合有可能拥有一个模型工厂(采用json并根据json的结构计算要生成的模型)而不是静态模型属性?
解决方法
我假设您收到的
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没有任何支持集合中多个模型的开箱即用的东西,但它也不会对您放在集合中的模型类型有任何限制.
在集合定义中指定模型类型只做一件事,它让Backbone知道要将原始JSON传递给集合而不是Backbone.Model对象时要创建的模型类型.如果您将Item模型添加到已经包含几个类别模型的集合中,则Backbone将弹出模型列表中没有问题;它不进行任何类型检查.
所以考虑到这一点,你可以使用集合提供的所有东西,除了传递原始的JSON;你需要自己处理.所以你的选择是预先建立你的模型,使它们成为Backbone.Model对象,或创建一些可以为你解析的东西.
对于第二个选项,解析器我建议将特殊变量传递给包含原始JSON的集合,然后在初始化函数中处理该变量.以下是一个例子:
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); } });
所以这有点黑客,但是您可以根据具体的字段(我的示例中的价格)来确定模型的类型,创建模型对象,然后将其添加到集合中.
你会这样称呼:
var myCollection = new CategoryCollection([],myJSON);
注意,你必须传递一个空数组作为第一个参数,因为这是你通常将一组模型传递给集合.
稍后在使用集合时,您可以使用简单的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!"); } });