同时保存几个骨干机型 [英] Save several Backbone models at once

查看:111
本文介绍了同时保存几个骨干机型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个骨干集合,型号的负载。

I have a Backbone collection with a load of models.

当一个特定的属性被设置在一个模型,它被保存,计算的负载断火和UI重新渲染。

Whenever a specific attribute is set on a model and it is saved, a load of calculations fire off and the UI rerenders.

不过,我希望能够一次设置多个模型的属性和只能做储蓄和重新描绘一旦他们所有的设置。当然,我不希望让几个HTTP请求一个操作,绝对不想有重新呈现接口的十倍。

But, I want to be able to set attributes on several models at once and only do the saving and rerendering once they are all set. Of course I don't want to make several http requests for one operation and definitely dont want to have to rerender the interface ten times.

我希望能找到Backbone.Collection)保存方法,将工作哪些型号hasChanged(一起重击他们作为JSON和欢送到后端。该重新描绘然后可以通过在收集的事件来触发。没有这样的运气。

I was hoping to find a save method on Backbone.Collection that would work out which models hasChanged(), whack them together as json and send off to the back end. The rerendering could then be triggered by an event on the collection. No such luck.

这似乎是一个pretty常见的需求,所以很奇怪,为什么骨干没有实现。这是否违背一个RESTful架构,以几件事情保存到一个终点?如果是这样,那又怎样?有没有办法,它的实用性,使1000个请求将持续1000小件物品。

This seems like a pretty common requirement, so am wondering why Backbone doesn't implement. Does this go against a RESTful architecture, to save several things to a single endpoint? If so, so what? There's no way it's practical to make 1000 requests to persist 1000 small items.

那么,是增加Backbone.Collection用我自己的方法保存在其所有车型的迭代唯一的解决办法,并建立了JSON所有已更改的那些和发送关闭到后端?或者有没有人有一个整洁的溶液(或我只是失去了一些东西!)?

So, is the only solution to augment Backbone.Collection with my own save method that iterates over all its models and builds up the json for all the ones that have changed and sends that off to the back end? or does anyone have a neater solution (or am I just missing something!)?

推荐答案

我已经结束了充实Backbone.Collection一对夫妇的方法来处理这​​个问题。

I have ended up augmenting Backbone.Collection with a couple of methods to handle this.

的saveChangeMethod创建要传递给Backbone.sync一个假人模型。所有骨干网的同步方法需要从一个模型是其url属性和方法的toJSON,所以我们可以很容易地敲这件事。

The saveChangeMethod creates a dummy model to be passed to Backbone.sync. All backbone's sync method needs from a model is its url property and toJSON method, so we can easily knock this up.

在内部,一个模型的toJSON方法只返回一个副本的属性(被发送到服务器),因此我们可以愉快地只使用,只是返回的车型阵列的方法的toJSON。 Backbone.sync stringifies这一点,这给了我们刚才的属性数据。

Internally, a model's toJSON method only returns a copy of it's attributes (to be sent to the server), so we can happily just use a toJSON method that just returns the array of models. Backbone.sync stringifies this, which gives us just the attribute data.

在成功saveChanged触发一次性事件的集合进行一次处理。已经打发在一个位code,获取它的每个已在任何批次的车型改变的属性一旦触发特定的事件。

On success, saveChanged fires off events on the collection to be handled once. Have chucked in a bit of code that gets it firing specific events once for each of the attributes that have changed in any of the batch's models.

Backbone.Collection.prototype.saveChanged = function () {
    var me = this,
        changed = me.getChanged(),
        dummy = {
            url: this.url,
            toJSON: function () {
                return changed.models;
            }
        },
        options = {
            success: function (model, resp, xhr) {
                for (var i = 0; i < changed.models.length; i++) {
                    changed.models[i].chnageSilently();
                }
                for (var attr in changed.attributes) {
                    me.trigger("batchchange:" + attr);
                }
                me.trigger("batchsync", changed);
            }
        };
    return Backbone.sync("update", dummy, options);
}

然后,我们只需要在一个集合getChanged()方法。这将返回一个对象具有两个属性,改变的车型阵列和属性已经改变的对象萎靡不振的:

We then just need the getChanged() method on a collection. This returns an object with 2 properties, an array of the changed models and an object flagging which attributes have changed:

Backbone.Collection.prototype.getChanged = function () {
    var models = [],
        changedAttributes = {};
    for (var i = 0; i < this.models.length; i++) {
        if (this.models[i].hasChanged()) {
            _.extend(changedAttributes, this.models[i].changedAttributes());
            models.push(this.models[i]);
        }
    }
    return models.length ? {models: models, attributes: changedAttributes} : null;
}

虽然这是用途骨干改变模式范式的轻微虐待,配料的整点是,当一个模型改变了我们什么都不想发生的(即任何事件火熄灭)。

Although this is slight abuse of the intended use of backbones 'changed model' paradigm, the whole point of batching is that we don't want anything to happen (i.e. any events to fire off) when a model is changed.

因此​​,我们必须通过{沉默:真正}到模型的set()方法,因此是很有意义的使用骨干hasChanged()来标记模型等进行保存。当然,如果你是出于其他目的默默地改变车型,这将是有问题的 - collection.saveChanged()将保存这些了,所以这是值得考虑设置一个替代标志。

We therefore have to pass {silent: true} to the model's set() method, so it makes sense to use backbone's hasChanged() to flag models waiting to be saved. Of course this would be problematic if you were changing models silently for other purposes - collection.saveChanged() would save these too, so it is worth considering setting an alternative flag.

在任何情况下,如果我们在做这种方式,保存时,我们需要确保骨干认为现在的模式没有改变(不触发其变更事件),所以我们需要手动操作模式,如果它没有被改变。该saveChanged()在我们的模型修改方法迭代并呼吁模式,这基本上是骨干model.change()方法不触发这个changeSilently()方法:

In any case, if we are doing this way, when saving, we need to make sure backbone now thinks the models haven't changed (without triggering their change events), so we need to manually manipulate the model as if it hadn't been changed. The saveChanged() method iterates over our changed models and calls this changeSilently() method on the model, which is basically just Backbone's model.change() method without the triggers:

Backbone.Model.prototype.changeSilently = function () {
    var options = {},
    changing = this._changing;
    this._changing = true;
    for (var attr in this._silent) this._pending[attr] = true;
    this._silent = {};
    if (changing) return this;

    while (!_.isEmpty(this._pending)) {
        this._pending = {};
        for (var attr in this.changed) {
        if (this._pending[attr] || this._silent[attr]) continue;
        delete this.changed[attr];
        }
        this._previousAttributes = _.clone(this.attributes);
    }
    this._changing = false;
    return this;
}

用法:

model1.set({key: value}, {silent: true});
model2.set({key: value}, {silent: true});
model3.set({key: value}, {silent: true});
collection.saveChanged();

RE。 RESTfulness ..这是不完全正确做PUT到集合的端点来改变其记录一些。技术上PUT应更换整个集合,虽然我之前曾经申请实际上需要更换整个集合,我很高兴地采取务实的做法。

RE. RESTfulness.. It's not quite right to do a PUT to the collection's endpoint to change 'some' of its records. Technically a PUT should replace the entire collection, though until my application ever actually needs to replace an entire collection, I am happy to take the pragmatic approach.

这篇关于同时保存几个骨干机型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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