嵌套在firebase集合模型中的集合没有添加功能 [英] The collection nested inside firebase collection's model doesn't have add function

查看:164
本文介绍了嵌套在firebase集合模型中的集合没有添加功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我正在尝试使用Firebase来存储基于主干框架的实时数据。

In my application, I am trying to use Firebase to store the real time data based on backbone framework.

问题是这样的:

我有一个子级模型和集合,它们都是通用骨干模型和集合。

The problem goes like this:
I have a sub level model and collection, which are both general backbone model and collection.

var Todo = Backbone.Model.extend({
    defaults: { 
        title: "New Todo",
        completed : true
    }
});

var Todocollection = Backbone.Collection.extend({
    model: Todo,
    initialize: function() {
        console.log("creating a todo collection...");
    },
});

然后有一个高级模型,其中包含sublevel集合作为属性。

And then there is a high level model, which contains the sublevel collection as an attribute.

var Daymodel = Backbone.Model.extend({
    defaults : {
        day: 1,
        agenda : new Todocollection()
    }
});

然后对于更高级别的集合,我将firebase集合

and then for the higher level collection, I will firebase collection

var DayCollection = Backbone.Firebase.Collection.extend({
    model: Daymodel
});

到目前为止,我可以正确地将数据添加到更高级别的集合,其中 day 属性和议程属性(应该是 TodoCollection )。

So far I can add data to the higher level collection correctly, which has a day attribute and an agenda attribute (which should be a TodoCollection).

问题是当我尝试将数据添加到子级别集合时,它无法正常工作。

The issue is when I try to add data to the sub-level collections, it can't work well.

this.collection.last()
    .get("agenda")
    .add({
        title: this.input.val(), 
        completed: false
    });

以上代码将位于View部分内。并且 this.collection.last()将获得最后一个模型。 get(agenda)应该是集合对象。

The above code will be inside the View part. And this.collection.last() will get the last model. get("agenda") should be the collection object.

但它无法正常工作。错误显示 this.collection.last(...)。get(...)。add 不是函数。

But it can't work. The error shows that this.collection.last(...).get(...).add is not a function.

调试后我发现 this.collection.last()。get(agenda)返回一个通用JS对象而不是集合对象。

After debugging I found that this.collection.last().get("agenda") returns a general JS object instead of collection object.

我进一步调试了如果我使用骨干集合作为外部集合 DayCollection 。一切都顺利。

I further debugged that if I use backbone collection as the outer collection DayCollection. Everything can go well.

如何解决这个问题?

推荐答案

为什么默认集合属性不再是集合?



当您获取或创建新的 Daymodel 时我假设看起来像这样:

Why the default collection attribute is not a collection anymore?

When you fetch, or create a new Daymodel which I assume looks like this:

{
    day: 1,
    agenda : [{
        title: "New Todo",
        completed : false
    }, {
        title: "other Todo",
        completed : false
    }]
}

默认的议程属性是一个 Todocollection 首先被原始对象数组取代。 Backbone不知道议程是一个集合,不会自动填充它。

The default agenda attribute which was a Todocollection at first gets replaced by a raw array of objects. Backbone doesn't know that agenda is a collection and won't automagically populates it.

这就是Backbone使用 默认值在模型创建时(第401行)

This is what Backbone does with the defaults at model creation (line 401):


var defaults = _.result(this, 'defaults');
attrs = _.defaults(_.extend({}, defaults, attrs), defaults);
this.set(attrs, options);


_.extend({},默认值,attrs)首先放置默认值,然后,它们被传递的 attrs

_.extend({}, defaults, attrs) puts the defaults first, but then, they're overwritten by the passed attrs.

以下是实现此目的的三种解决方案。只使用其中一个,或根据以下内容创建自己的。

Below are three solutions to accomplish this. Use only one of them, or create your own based on the followings.

保持 Todocollection 退出 Daymodel 模型并仅创建在需要时收集,例如假设 DayView

Keep the Todocollection out of the Daymodel model and only create the collection when you need it, like in the hypothetical DayView:

var DayView = Backbone.View.extend({
    initialize: function() {
        // create the collection in the view directly
        this.agenda = new Todocollection(this.model.get('agenda'));
    },
    /* ...snip... */
});

然后,当您想要在模型中保留更改时,您只需将集合模型恢复进入 Daymodel

Then, when there are changes you want to persist in the model, you just put the collection models back into the Daymodel:

this.model.set('agenda', this.collection.toJSON());



将集合放入模型的属性



您可以创建一个懒惰地创建集合并将其作为属性保留在模型中的函数,而不是属性,保留属性 hash clean

Put the collection into a property of the model

Instead of an attribute, you could make a function which lazily create the collection and keeps it inside the model as a property, leaving the attributes hash clean.

var Daymodel = Backbone.Model.extend({
    defaults: { day: 1, },
    getAgenda: function() {
        if (!this.agenda) this.agenda = new Todocollection(this.get('agenda'));
        return this.agenda;
    }
});

然后,模型控制集合,并且可以与已共享模型的所有内容轻松共享,每个实例只创建一个集合。

Then, the model controls the collection and it can be shared easily with everything that shares the model already, creating only one collection per instance.

保存模型时,仍需要将原始模型传递回属性哈希。

When saving the model, you still need to pass the raw models back into the attributes hash.

你可以完成你已经尝试做的事情只需很小的更改。

You can accomplish what you're already trying to do with small changes.


  1. 永远不要将对象放入默认值

  1. Never put objects into the defaults

...而不使用返回对象的函数。

...without using a function returning an object instead.

var Daymodel = Backbone.Model.extend({
    defaults: function() {
        return {
            day: 1,
            agenda: new Todocollection()
        };
    },
});

否则,议程集合将被共享在 Daymodel 的每个实例之间,因为在创建 Daymodel 类时只创建一次集合。

Otherwise, the agenda collection would be shared between every instances of Daymodel as the collection is created only once when creating the Daymodel class.

这也适用于对象文字,数组,函数(为什么你还要把它放在默认值中?)。

This also applies to object literals, arrays, functions (why would you put that in the defaults anyway?!).

确保它始终是一个集合。

var Daymodel = Backbone.Model.extend({
    defaults: { day: 1, },
    initialize: function(attrs, options) {
        var agenda = this.getAgenda();
        if (!(agenda instanceof Todocollection)) {
            // you probably don't want a 'change' event here, so silent it is.
            return this.set('agenda', new Todocollection(agenda), { silent: true });
        }
    },
    /**
     * Parse can overwrite attributes, so you must ensure it's a collection
     * here as well.
     */
    parse: function(response) {
        if (_.has(response, 'agenda')) {
            response.agenda = new Todocollection(response.agenda);
        }
        return response;
    },
    getAgenda: function() {
        return this.get('agenda');
    },
    setAgenda: function(models, options) {
        return this.getAgenda().set(models, options);
    },
});


  • 确保它可序列化。

    var Daymodel = Backbone.Model.extend({
        /* ...snip... */
        toJSON: function(options) {
            var attrs = Daymodel.__super__.toJSON.apply(this, arguments),
                agenda = attrs.agenda;
            if (agenda) {
                attrs.agenda = agenda.toJSON(options);
            }
            return attrs;
        },
    });
    

    如果您将集合放在模型属性中,可以轻松应用,如上所述。

    This could easily apply if you put the collection in a model property as explained above.

    避免意外覆盖议程属性。

    Avoid accidentally overriding the agenda attribute.

    这与第2点并列,因为它很容易被忽视,或者其他人(或其他lib)可以做到这一点。

    This goes alongside with point 2 and that's where it's getting hard as it's easy to overlook, or someone else (or another lib) could do that down the line.

    可以覆盖 save set 函数来添加检查,但是它过于复杂而没有太多从长远来看。

    It's possible to override the save and set function to add checks, but it gets overly complex without much gain in the long run.



    模特中收藏的缺点是什么?



    我谈到完全避免在模型中使用它,或者懒洋洋地创建它。那是因为如果你实例化很多模型会变得非常慢,如果每个模型都嵌套多次,那么它会慢一些(模型有一组模型,有其他模型集合等)。

    What's the cons of collection in models?

    I talked about avoiding it inside a model completely, or lazily creating it. That's because it can get really slow if you instantiate a lot of models and slower if each models is nested multiple times (models which have a collection of models, which have other collections of models, etc).

    按需创建时,您只需在需要时使用机器资源,并且仅在需要时使用。例如,现在不在屏幕上的任何模型都不会创建它们的集合。

    When creating it on demand, you only use the machine resources when you need it and only for what's needed. Any model that's not on screen now for example, won't get their collection created.

    也许这项工作正常工作太多了,所以一个完整的解决方案可能有所帮助,并且有一对。

    Maybe it's too much work to get this working correctly, so a complete solution might help and there are a couple.

    • Backbone relational
    • backbone-nested
    • backbone-nested-models
    • backbone-deep-model

    这篇关于嵌套在firebase集合模型中的集合没有添加功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆