使用MVC/Backbone.js实现复合模式

whe*_*hys 10 javascript model-view-controller design-patterns composite backbone.js

我的webapp有一个复合结构,即每个Category集合可以包含单个Items和其他Categories的混合作为其行/节点/子节点(这里不确定正确的术语).实际上,它比这更简单,因为每个集合都由一个模型Category表示,所以基本上每个Category集合都有Item模型和Category模型作为它的子元素.

一般来说,这是使用MVC实现此结构的可行方法吗?更具体地说,在Backbone.js中,集合是否可以拥有模型工厂(获取json并根据json的结构计算生成哪个模型)而不是静态模型属性?

Kev*_*eel 5

我假设您在JSON中收到的类别/项目列表看起来像这样......

{
    'id': 1,
    'name': 'My 1st Category',
    'children': [
        {
            'id': 2,
            'name': 'My 2nd Category',
            'children': []
        },
        {
            'id': 1,
            'name': 'An Item',
            'price': 109.99
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
});
Run Code Online (Sandbox Code Playgroud)

所以它有点hacky,但你根据它是否具有特定字段(price在我的示例中)确定模型的类型,创建模型对象,然后将其添加到集合中.

然后你会这样称呼它:

var myCollection = new CategoryCollection([], myJSON);
Run Code Online (Sandbox Code Playgroud)

请注意,您必须传递一个空数组作为第一个参数,因为您通常会将一组模型传递给集合.

稍后使用该集合时,您可以确定您是在处理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!");
    }
});
Run Code Online (Sandbox Code Playgroud)


Mau*_*ras 1

是的你可以。我以前做过。我认为这个链接可以帮助你:http ://documentcloud.github.com/backbone/#Collection-model

这是我用于项目的主要脚本之一:https://gist.github.com/b65893e0c2e3c46d3dc1