使用MVC/Backbone.js实现复合模式
Implementing a composite pattern using MVC/Backbone.js
我的webapp有一个复合结构,即每个Category集合可以包含单独的Items和其他Category的混合物作为其行/节点/子项(此处不确定正确的术语)。事实上,它比这简单一点,因为每个集合都由一个模型Category表示,所以本质上每个Category集合都有Item模型和Category模型作为其子级。
一般来说,这是使用MVC实现这种结构的一种可取方式吗?更具体地说,在Backbone.js中,集合是否可以有一个模型工厂(获取json并根据json的结构计算生成哪个模型),而不是静态模型属性?
我假设您收到的JSON中的Category/Items列表如下。。。
{
'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);
}
});
因此,这有点麻烦,但您可以根据模型是否有特定字段(在我的示例中为price
)来确定模型的类型,创建模型对象,然后将其添加到集合中。
然后你可以这样称呼它:
var myCollection = new CategoryCollection([], myJSON);
请注意,您必须传递一个空数组作为第一个参数,因为这是通常向集合传递一组模型的方式。
稍后在使用集合时,您可以使用简单的instanceof
检查来确定是处理Item
还是Category
:
_.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!");
}
});
可以。我以前做过。我认为这些链接可以帮助您:http://documentcloud.github.com/backbone/#Collection-型号
以下是我在项目中使用的主要脚本之一:https://gist.github.com/b65893e0c2e3c46d3dc1
在检索和保存模型数据时,只需覆盖主干内部使用的内置公共方法parse和toJSON即可实现。
首先,当您从数据库中检索模型时,您应该覆盖模型的parse
方法,以创建表示示例中给定项目的模型。
然后在保存时,toJSON
方法用于将数据序列化回服务器可以理解的格式——在那里,您只需在每个项的Model上调用toJSON
方法,将其序列化为后端可以识别的格式。如果您查看Backbone.sync
的代码,您会发现如果没有传递自定义数据,则模型总是使用toJSON进行序列化。
如果你需要更详细的信息,请告诉我,尽管我相信你应该可以从这里获得!
是的,您可以在主干的集合中使用Factory方法模式来创建模型。假设@kpeel的答案中建议的数据结构,您可以定义
// 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");
这里有一个jsFiddle,上面的代码可以用来玩。
- 如何使用动画实现纸张推车
- 客户端服务器REST API captcha实现
- 如何实现此布局
- Meteor忘记了密码的实现
- 使用Native Sockets在Android中实现WebSockets
- 在样板文件中实现Ajax
- instanceof是如何在JavaScript中实现的
- 如何正确实现Jquery多选小部件
- 实现一个建立在google.com之上的自定义搜索引擎
- 多个组件是如何实现的
- window.location使用jquery mobile实现chrome跳转
- 如何在OpenERP中实现网络摄像头
- Node.js使用Series函数(模式?)实现流控制时出现意外结果
- javascript加密实现,包括可信否认
- 实现比较方法的最佳实践是什么;s的比较类型是在运行时选择的
- 如何让程序员在javascript中实现正确的回调
- 如何使用自定义辅助对象(handler)实现嵌套的每个循环
- AngularJS智能表全局配置实现
- Expressjs/AngularJS:实现req-flash后出错
- 使用MVC/Backbone.js实现复合模式