【问题标题】:Backbone Collection with multiple models?具有多个模型的主干集合?
【发布时间】:2012-12-25 04:26:49
【问题描述】:

我正在学习 Backbone。

我想创建一个列表,其中可以包含具有不同属性的不同模型。

例如,列出文件夹内容,其中可能包括类型文件的模型和类型文件夹的模型,以任意顺序。

file : {
  title : "",
  date : "",
  type : "",
  yaddayadda : ""
}

folder : {
  title : "",
  date : "",
  haminahamina : ""
}

在 Backbone 中表示这一点的正确方法是什么?是否可以有一个包含多个模型的集合?

【问题讨论】:

标签: javascript backbone.js backbone.js-collections


【解决方案1】:

创建您的其他模型继承自的基本模型:

var DataModel = Backbone.Model.extend({
    // Whatever you want in here
});

var FileModel = DataModel.extend({
    // Whatever you want in here
});

var FolderModel = DataModel.extend({
    // Whatever you want in here
});

并使集合的model 类型为相同的基本模型:

var DataCollection = Backbone.Collection.extend({
    model: DataModel
});

【讨论】:

  • 感谢您的回复。当 DataCollection 传递给要渲染的视图时,您将如何渲染属于 FileModel 或 FolderModel 的属性?
  • 您可以随时检查obj instanceof FileModel(或FolderModel)是否正确渲染。
  • 我也是这样做的,但是您如何传入您所说的 DataCollection(AJAX 调用)?如果是这种情况,您将必须检查响应中是否存在该唯一属性(即 if (someModel.someUniqueProperty) { // 使用将处理该属性值的视图渲染它};)。
【解决方案2】:

您也可以采用主干方式。查看文档backbone collection

基本上,在这种情况下,您将创建不同的模型,并添加一个决胜局属性,例如“type”。

var file = Backbone.Model.extend({
        defaults: {
            // will need to include a tie breaker attribute in both models
            type: 'file'
        }
    }),
    folder = Backbone.Model.extend({
        defaults: {
            // tie breaker
            type: 'folder'
        }
    });

var fs = Backbone.Collection.extend({
    model: function(model, options) {
        switch(model.type) {
            case 'file':
                return new file(model, options);
            case 'folder':
                return new folder(model, options);
        }
    }
});

// after that just add models to the collection as always
new fs([
    {type: 'file',name: 'file.txt'},
    {type: 'folder',name: 'Documents'}
]);

【讨论】:

  • 我喜欢这种方法,它不仅是“主干方式”,而且不需要上面提到的额外业务逻辑@dennis,实际上您根本不需要任何变通方法,因为它一切都会像你期望的那样工作。另外,我相信您的意思是:var fs = Backbone.Collection.extend({
  • 请注意这会破坏this.model.prototype.idAttribute,因此您应该查看Maciej 的answer,它使用ModelFactory.prototype.idAttribute 解决了这个问题。
  • 或者只是覆盖集合modelId函数以避免重复。
【解决方案3】:

在这种情况下,主干documention 不完整。与merge:true 选项和idAttribute 一起使用时,它将不起作用。在这种情况下,您需要:

var ModelFactory = function (attr, options) {
  switch (attr.type) {
    case 'file':
      return new file(attr, options);
    case 'folder':
      return new folder(attr, options);
  }
};
ModelFactory.prototype.idAttribute = '_id';

var fs = Backbone.Model.extend({
   model: ModelFactory
});

【讨论】:

  • ModelFactory.prototype.idAttribute 在这里非常重要,因为它可以避免重复。
  • 覆盖集合 modelId 函数将是等效的。
【解决方案4】:
        var bannedList = app.request('rest:getBan');
        var whiteIpList = app.request("rest:getWhite");
        var whiteGroupList = app.request("rest:....");
        $.when(bannedList, whiteIpList, whiteGroupList).
done(function (bannedList, whiteIpList, whiteGroupList) {
            var collection = new Backbone.Collection();
            collection.add(bannedList);
            collection.add(whiteIpList);
            collection.add(whiteGroupList);

        });


    app.reqres.setHandler("rest:getBannedList", function (data) {
        return API.getBannedList(data);
    });
    getBannedList: function (data) {
                var user = new Backbone.Model();
                user.url = '/banned';
                user.cid = 'bannedList';
                var defer = $.Deferred();

                user.fetch({
                    type: 'GET',
                    data: data,
                    success: function (data) {
                        defer.resolve(data);
                    },
                    error: function (data) {
                        defer.reject(data);
                    }
                });
                return defer.promise();
            },

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    相关资源
    最近更新 更多