Backbone.js 模型与集合

Posted

技术标签:

【中文标题】Backbone.js 模型与集合【英文标题】:Backbone.js model with collection 【发布时间】:2011-10-31 17:29:47 【问题描述】:

我有 2 个模型和一个集合。 JobSummary 是模型,JobSummaryListJobSummary 项目的集合,然后我有一个 JobSummarySnapshot 模型,其中包含 JobSummaryList

JobSummary = Backbone.Model.extend();

JobSummaryList = Backbone.Collection.extend(
    model: JobSummary
);

JobSummarySnapshot = Backbone.Model.extend(
    url: '/JobSummaryList',

    defaults: 
        pageNumber: 1,
        summaryList: new JobSummaryList()
    
);

当我在JobSummarySnapshot 对象上调用fetch 时,它会获取所有内容...除非我在summaryList 集合中移动,它们都是object 类型而不是JobSummary

我认为这是有道理的,因为除了defaults 对象之外,它不知道summaryList 应该是JobSummaryList 类型。我可以遍历每个项目并将其转换为 JobSummary 对象,但我希望有一种方法可以做到这一点,而无需手动进行。

这是我的测试代码(工作 jsfiddle here):

var returnData = 
    pageNumber: 3,
    summaryList: [
        
        id: 5,
        name: 'name1',
    
        id: 6,
        name: 'name2'
    ]
; 

var fakeserver = sinon.fakeServer.create();
fakeserver.respondWith('GET', '/JobSummaryList', [200,

    'Content-Type': 'application/json',
                                JSON.stringify(returnData)]);

var callback = sinon.spy();


var summarySnapshot = new JobSummarySnapshot();
summarySnapshot.bind('change', callback);

summarySnapshot.fetch();
fakeserver.respond();

var theReturnedList = callback.getCall(0).args[0].attributes.summaryList;

_.each(theReturnedList, function(item) 
    console.log('Original Item: ');
    console.log(item instanceof JobSummary); // IS FALSE
    var convertedItem = new JobSummary(item);
    console.log('converted item: ');
    console.log(convertedItem instanceof JobSummary); // IS TRUE
);

更新: 我突然想到我可以覆盖 parse 函数并以这种方式设置它......我现在有这个:

JobSummarySnapshot = Backbone.Model.extend(
    url: '/JobSummaryList',

    defaults: 
        pageNumber: 1,
        summaryList: new JobSummaryList()
    ,

    parse: function(response) 
        this.set(pageNumber: response.pageNumber);

        var summaryList = new JobSummaryList();
        summaryList.add(response.summaryList);

        this.set(summaryList: summaryList);
    
);

到目前为止,这有效。留下问题以防有人对此发表评论......

【问题讨论】:

【参考方案1】:

你的parse() 函数不应该set() 任何东西,最好只返回属性,Backbone 会负责设置它。例如

parse: function(response) 
    response.summaryList = new JobSummaryList(response.summaryList);
    return response;

无论你从parse() 返回什么都是passed to set()

不返回任何内容(就像返回undefined)与调用set(undefined) 相同,如果您的自定义validate()/set() 方法期望,这可能会导致它无法通过验证,或者一些其他意外结果得到一个对象。如果您的验证或set() 方法因此失败,则不会调用传递给Backbone.Model#fetch()options.success 回调。

此外,为了使其更通用,以便 set()ing 来自其他地方(不仅来自服务器响应)的普通对象也会影响它,您可能想要覆盖 set() 代替:

set: function(attributes, options) 
    if (attributes.summaryList !== undefined && !(attributes.summaryList instanceof JobSummaryList)) 
        attributes.summaryList = new JobSummaryList(attributes.summaryList);
    
    return Backbone.Model.prototype.set.call(this, attributes, options);

您可能还会发现 Backbone-relational 很有趣 - 它可以更轻松地处理嵌套在模型中的集合/模型。

edit忘记从set()方法返回了,代码现在更新了

【讨论】:

非常感谢。我今天只看了一半的东西感到内疚,再一次,它咬了我。它在文档中清楚地说明,正如您上面提到的,您从 parse 函数返回 obj ......但我不知何故错过了这一点。再次感谢。

以上是关于Backbone.js 模型与集合的主要内容,如果未能解决你的问题,请参考以下文章

Backbone.js 模型和集合的最佳实践

多个模型子类的 Backbone.js 集合

Backbone.js 将两个不同的模型添加到同一个集合中

渲染 Backbone.js 集合

Backbone.js:在现实世界的应用程序中呈现集合

Backbone.js - 按顺序插入新的视图项