【问题标题】:Backbone.js model with collectionBackbone.js 模型与集合
【发布时间】: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});
    }
});

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

【问题讨论】:

    标签: javascript ajax json backbone.js


    【解决方案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 ......但我不知何故错过了这一点。再次感谢。
    猜你喜欢
    • 2013-07-24
    • 1970-01-01
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-11
    • 2011-10-19
    相关资源
    最近更新 更多