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

Implementing a composite pattern using MVC/Backbone.js

本文关键字:实现 复合 模式 js Backbone MVC 使用      更新时间:2023-09-26

我的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,上面的代码可以用来玩。