LocalStorage 和 URL 在一个 Backbone 集合中

LocalStorage and URL in one Backbone collection

我有一个集合,它从 URL 中获取数据。

BarCollection = Backbone.Collection.extend({
  model: BarModel,
  url: // Some URL
});

但问题是我不仅要从 URL,还要从本地存储中为这个集合获取数据。我希望我能做这样的事情:

BarCollection = Backbone.Collection.extend({
  model: BarModel,
  url: // Some URL,
  localStorage: new Backbone.LocalStorage('bars')
});

但是 .fetch() 方法无法同时从 url 和本地存储中获取数据。

简单的解决方法是创建两个不同的集合:一个用于 URL,一个用于本地存储。获取后只需合并它们。

BarCollection = Backbone.Collection.extend({
  model: BarModel,
  url: // Some URL
});

LocalBarCollection = Backbone.Collection.extend({
  model: BarModel,
  localStorage: new Backbone.LocalStorage('local-contributors')
});

不知道有没有更漂亮的方法呢

要使任何集合或模型能够从 localStorage 和服务器同步,可以覆盖 Backbone 的同步功能:

Backbone.sync = (function(sync) {
    return function(method, model, options) {
        options = options || {};
        var key = _.result(model, 'localStorage'),
            response;

        // if the localStorage property exist on the model/collection
        // first try to sync with the localStorage
        if (key) {
            switch (method) {
                case 'create':
                case 'update':
                    var data = model.toJSON(),
                        text = JSON.stringify(data);
                    localStorage.setItem(key, text);
                    break;
                case 'delete':
                    localStorage.removeItem(key);
                    break;
                case 'read':
                    response = JSON.parse(localStorage.getItem(key));
                    if (response) model.set(response, { parse: true });
                    break;
            }
        }

        // then, always sync with the server as it normally would
        return sync.apply(this, arguments);
    };
})(Backbone.sync);

这样,如果模型或集合作为 localStorage 属性,它将首先与 localStorage 同步,然后进行原始同步。

示例模型和集合:

var BarModel = Backbone.Model.extend({
    urlRoot: 'some/url',
    localStorage: function() {
        return 'bars-' + this.id;
    },
});

var BarCollection = Backbone.Collection.extend({
    model: BarModel,
    url: '/some/url',
    localStorage: 'bars',
});