简体   繁体   English

Backbone.js模型与集合

[英]Backbone.js model with collection

I have 2 models and one collection. 我有2个模型和一个集合。 JobSummary is a model, JobSummaryList is a collection of JobSummary items, and then I have a JobSummarySnapshot model that contains a JobSummaryList : JobSummary是一个模型, JobSummaryListJobSummary项的集合,然后我有一个包含JobSummaryListJobSummarySnapshot模型:

JobSummary = Backbone.Model.extend({});

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

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

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

When I call fetch on the JobSummarySnapshot object, it gets everything... Except when I move through the summaryList collection they are all of type object and not JobSummary . 当我在JobSummarySnapshot对象上调用fetch时,它会获取所有内容......除非我在summaryList集合中移动, summaryList它们都是类型object而不是JobSummary

I suppose this makes sense since other than the defaults object, it doesn't know that the summaryList should be of type JobSummaryList . 我认为这是有道理的,因为除了defaults对象之外,它不知道summaryList应该是JobSummaryList类型。 I can go through each item and convert it to a JobSummary object, but I was hoping there was a way to do it without having to do it manually. 我可以浏览每个项目并将其转换为JobSummary对象,但我希望有一种方法可以在不必手动操作的情况下完成。

Here's my test code (working jsfiddle here ): 这是我的测试代码(在这里工作jsfiddle ):

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
});

UPDATE: It occurred to me that I could override the parse function and set it that way... I have this now: 更新:我想到我可以覆盖解析函数并设置它......我现在有这个:

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});
    }
});

This works so far. 这项工作到目前为止。 Leaving the question open in case someone has comment on it.... 保留问题,以防有人评论....

Your parse() function shouldn't set() anything, its a better practice to just return the attributes, Backbone will take care of setting it. 你的parse()函数不应该set()任何东西,它只是返回属性的更好的做法,Backbone将负责设置它。 eg 例如

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

Whatever you return from parse() is passed to set() . 无论从parse()返回什么,都会传递给set()

Not returning anything (which is like returning undefined ) is the same as calling set(undefined) , which could cause it not to pass validation, or some other unexpected results if your custom validate() / set() methods expects to get an object. 不返回任何内容(类似于返回undefined )与调用set(undefined) ,这可能导致它无法通过验证,或者如果您的自定义validate() / set()方法需要获取对象,则会导致其他一些意外结果。 If your validation or set() method fails because of that, the options.success callback passed to Backbone.Model#fetch() won't be called. 如果您的validation或set()方法因此失败,则不会调用传递给Backbone.Model#fetch()options.success回调。

Also, to make this more generic, so that set() ing to a plain object from other places (and not only from the server response) also effects it, you might want to override set() instead: 另外,为了使它更通用,以便set()从其他地方(而不仅仅是服务器响应)的普通对象也会影响它,你可能想要覆盖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);
}

You might also find Backbone-relational interesting - it makes it much easier to deal with collections/models nested inside models. 您可能还会发现Backbone-relational很有趣 - 它可以更轻松地处理嵌套在模型中的集合/模型。

edit I forgot to return from the set() method, the code is now updated 编辑我忘了从set()方法返回,现在代码已更新

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM