【问题标题】:Different model types in one collection Backbone一个集合中的不同模型类型
【发布时间】:2015-02-26 23:31:11
【问题描述】:

骨干网 1.1.2
下划线 1.7.0
jQuery 1.11.1

我有一个包含消息的集合。 我的消息可以是不同的类型(每种类型的 api 中的端点都不同,但我有一个端点允许我执行一个请求并获取所有消息)

当 Collection.fetch() 在基于现有属性填充集合时,我需要能够定义要使用的模型。

我已经按照这里的建议尝试过:A Backbone.js Collection of multiple Model subclasses 以及主干文档backbonejs.org

我的代码是这样的

model: function (attr, options) {
    if(attr.hasOwnProperty('prop')){
        return new PropModel(attr,options);
    }
    else if(attr.hasOwnProperty('another_prop')){
        new AnotherPropModel(attr,options);
    }
},

attr 值只是一大堆对象,所以如果不以某种方式遍历,这个解决方案对我来说毫无意义,而且很明显为什么它不起作用。

我是否正确处理了这个问题是否有其他方法可以做到这一点?

---更新----

我也尝试在集合的解析函数中这样做,但我的集合只是空的

parse: function (resp, options) {
    _.each(resp, _.bind(function (r) {
        console.log(this);
        if(r.hasOwnProperty('prop')){
            this.add(new PropModel(r));
        }else{
            this.add(new AnotherPropModel(r));
        }
    },this));
}

【问题讨论】:

  • 模型之间是否存在关键差异?还是只是网址?
  • @anAgent 每个属性都不同,所以我想在渲染模板时对每个模型进行类型转换。我想我可以在模板中执行相同的逻辑,但我更喜欢将逻辑保留在模板之外,以便在需要时轻松切换模板引擎
  • url 对我来说也很重要,因为属性不同。即使消息可以分组,它们在我系统的其他区域也是独立的
  • 看起来你在正确的道路上 - 如果需要,改变集合的 fetch url,然后在那个函数中你应该只需要返回模型函数(不是新的) - if (attr.modelType === 'mailItem') { return MailItemModel; }
  • @DominicTobias 在 attr 我没有模型类型。我有一个从 Json 解析的数组对象。

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


【解决方案1】:

所以解决方案是混合使用模型函数和返回。

解释如下:

首先我们有解析函数 这只是我们更改从服务器收到的响应的入口点

parse: function (resp, options) {
    return resp;
}

在我的例子中,服务器返回一个 Object of Object

{{1:data},{2:data}}

首先,这很奇怪,显然需要解决。 重要的一点是: 当骨干网评估解析的响应返回时,它需要决定每个模型在哪里中断,就像定义一个新模型一样。

Backbone 将对象视为单个模型,就我而言,我有一个大对象,我得到一个大模型...这就是为什么模型函数中的 attrs 参数是一大堆数据。

所以我只是在解析函数中更改了我的响应,瞧!模型函数中的一切都按预期工作:

代码如下:

model: function (attr, options) {
    if(attr.hasOwnProperty('prop')){
        return new PropModel(attr,options);
    }
    else if (attr.hasOwnProperty('anotherProp')){
        return new AnotherPropModel(attr,options);
    }
},

parse: function (resp, options) {
    var response = [];
    _.each(resp, _.bind(function (r) {
        response.push(r);
    },this));
    return response;
}

我确信有更好的方法可以将对象解析为数组,但现在这可行,我又笑了!!

这篇文章引导我找到解决方案: A collection of muppets

【讨论】:

  • 只是一个不需要使用 _.bind 的注释,因为 _.each 的第三个参数是上下文。其次,您没有调用 _.each 范围之外的任何内容,因此不需要。
  • 你是对的!!我已经删除了_.bind,我想我只是养成了失去作用域的习惯,所以我倾向于将回调函数绑定为习惯。
【解决方案2】:

您可以执行以下操作 - 对不同类型做出反应(如果可能),然后提供不同的 URL。然后,一旦 JSON 模型在模板中,您就可以按照自己喜欢的方式呈现 HTML:

Json 示例

"[{"id":1,"Type":"Person"},{"id":2,"Type":"Business"}]"

示例模型

var Person = Backbone.Model.extend({

    keyTypes: {
        Person: 'Person',
        Business: 'Business'
    },

    url: function() {
        // we are assuming only two types. Change logic if there are three or more types.
        return this.get('Type') === this.keyTypes.Person ? '/api/people' : '/api/businesss';
    }

});

收藏

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

查看

var View = Backbone.View.extend({

    initialize: function() {
        this.collection = new Collection()
            .on('fetch', this.render, this);
    },

    bootstrap: function() {
        this.collection.fetch();
    }

    render: function() {
        this.$el.html(_.template({
            models: this.collection.toJSON()
        }));
    }
})

** !!更新 !! **

如果你还想继续使用 parse,可以查看以下内容。

parse: function (data, options) {

    var models = [];
    _.each(data, function (entity) {
        // this is IE8 Safe....
        var model = Object.prototype.hasOwnProperty.call(entity,'prop') ? PropModel : AnotherPropModel;
        models.push(new model(entity));    
    });

    return models;
}

【讨论】:

  • 我知道这将如何解决多个 url 端点,但我仍然不明白这如何为我定义模型以便我可以进行类型转换?
  • 它回答了类型转换的要求——所以我同意它不能满足你的确切问题。我认为,如果您开始进行类型转换,您将开始遇到其他长期问题并且更难测试。
  • 我实际上是类型转换的粉丝,因为这会强制理解并允许快速失败。你的更新是有道理的,我忘了提到我正在开发一个 chrome 扩展......所以目前不太担心跨浏览器兼容性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
相关资源
最近更新 更多