Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/445.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用MVC/Backbone.js实现复合模式_Javascript_Model View Controller_Design Patterns_Backbone.js_Composite - Fatal编程技术网

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

Javascript 使用MVC/Backbone.js实现复合模式,javascript,model-view-controller,design-patterns,backbone.js,composite,Javascript,Model View Controller,Design Patterns,Backbone.js,Composite,My webapp具有复合结构,即每个类别集合可以包含单个项目和其他类别的混合,作为其行/节点/子项(不确定此处的术语是否正确)。事实上,它比这个简单一点,因为每个集合都由一个模型Category表示,所以本质上每个Category集合都有条目模型和Category模型作为其子对象 一般来说,这是使用MVC实现此结构的一种可取方法吗?更具体地说,在Backbone.js中,集合是否可以有一个模型工厂(获取json并根据json的结构计算要生成的模型),而不是一个静态模型属性?是的,可以。我以前做

My webapp具有复合结构,即每个类别集合可以包含单个项目和其他类别的混合,作为其行/节点/子项(不确定此处的术语是否正确)。事实上,它比这个简单一点,因为每个集合都由一个模型Category表示,所以本质上每个Category集合都有条目模型和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没有任何现成的支持集合中多个模型的功能,但它也没有对集合中模型类型的任何限制

在集合定义中指定模型类型只做一件事,如果将原始JSON传递给集合而不是
Backbone.model
对象,它会让主干知道要创建什么模型类型。如果将
模型添加到已包含一些
类别
模型的集合中,则将其弹出到模型列表中不会有问题;它不做任何类型检查

因此,考虑到这一点,您可以使用集合提供的几乎所有内容,除了传递原始JSON;你需要自己处理。因此,您的选择是预先构建模型,将它们制作成
主干.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
检查来确定您是在处理
项目
还是
类别

_.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!");
    }
});

在检索和保存模型数据时,只需覆盖内置的公共方法并由主干网内部使用,就可以相当简单地实现这一点

首先,从数据库中检索模型时,应该覆盖模型的
parse
方法,以创建表示示例中给定项的模型

然后在保存时,使用
toJSON
方法将数据序列化回服务器可以理解的位置-在这里,您只需调用每个项目模型上的
toJSON
方法,将其序列化为后端可以识别的格式。如果查看
Backbone.sync
的代码,您将看到如果没有传递自定义数据,则总是使用toJSON对模型进行序列化


如果您需要更详细的信息,尽管我相信您应该可以从这里获取

是的,您可以使用工厂方法模式在主干的集合中创建模型。假设中建议的数据结构,您可以定义

// 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);
访问类别的子项及其
子项
属性,例如

  rootItem.children.get(2).get("name");

这是一个值得玩味的话题。

简而言之,我会说,“我不明白为什么不”,但我很好奇其他人会怎么说。我真的不知道你在这方面做了什么。我所能看到的只是一种类型的模型,TransactionDetail,被添加到集合中,wehn我想自由添加两种。自从发布这个问题以来,我开始编辑主干以尝试获得我所需要的,但它为集合内置了唯一的ID规则,所以我认为我需要创建一些桥接模型,使用从模型类型和ID生成的ID。但我仍然有兴趣看看是否有更好的方法。好吧,我希望你能找到你需要的方法。非常幸运。他是对的,您可以将工厂函数作为集合类的模型属性。。。使用options参数走私原始数据的好主意。哈哈,谢谢。我认为这比破解Backbone.js源代码本身更容易。我想,为了清理它,您可以创建一个包装类,您只需将JSON传递给该类,然后为您创建并返回集合。是的,我也想劫持/包装一些其他的集合方法,主要是作为内部主干。模型希望id是唯一的,例如,我需要调整id,以便它接受一个键值对{modelType:id},或者同样简化为格式化字符串。啊,你是对的,需要更多的黑客攻击。我想避免所有这些的另一种方法是在类别模型本身中有两个集合,一个用于类别,一个用于项目。这样你就不需要自定义集合了——所有的解析逻辑都在模型中。我可以写一个如果您需要更详细的解释,请回答。我认为这可能是解决方案的一部分,但也有其他方法需要调整,例如Backbone.Collection.\u prepareModel(对于我的应用程序,我可以确保从不将原始json传递到Collection.add(它在内部调用.prepareModel),但如果有一个解决方案能够使用Collection.add处理JSON数组,那就太好了。我认为覆盖模型的
set
方法来解析属性/JSON传递