Javascript Backbone.js 模型与集合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7140741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:01:01  来源:igfitidea点击:

Backbone.js model with collection

javascriptajaxjsonbackbone.js

提问by Bryce Fischer

I have 2 models and one collection. JobSummaryis a model, JobSummaryListis a collection of JobSummaryitems, and then I have a JobSummarySnapshotmodel that contains a JobSummaryList:

我有 2 个模型和一个系列。JobSummary是一个模型,JobSummaryList是一个JobSummary项目的集合,然后我有一个JobSummarySnapshot包含以下内容的模型JobSummaryList

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 fetchon the JobSummarySnapshotobject, it gets everything... Except when I move through the summaryListcollection they are all of type objectand not JobSummary.

当我调用fetchJobSummarySnapshot对象时,它会获取所有内容......除了当我在summaryList集合中移动时,它们都是 typeobject而不是JobSummary

I suppose this makes sense since other than the defaultsobject, it doesn't know that the summaryListshould be of type JobSummaryList. I can go through each item and convert it to a JobSummaryobject, but I was hoping there was a way to do it without having to do it manually.

我想这是有道理的,因为除了defaults对象之外,它不知道summaryList应该是 type JobSummaryList。我可以浏览每个项目并将其转换为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:

更新:我突然想到我可以覆盖 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});
    }
});

This works so far. Leaving the question open in case someone has comment on it....

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

回答by shesek

Your parse()function shouldn't set()anything, its a better practice to just return the attributes, Backbone will take care of setting it. e.g.

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

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. If your validation or set()method fails because of that, the options.successcallback passed to Backbone.Model#fetch()won't be called.

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

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-relationalinteresting - it makes it much easier to deal with collections/models nested inside models.

您可能还会发现Backbone-relational很有趣——它使处理嵌套在模型中的集合/模型变得更加容易。

editI forgot to return from the set() method, the code is now updated

编辑我忘记从 set() 方法返回,代码现在更新