Backbone.js:无法将相同的模型添加到集合中两次

时间:2011-07-17 13:16:52

标签: javascript backbone.js

我刚开始使用backbone.js。我在从服务器获取数据时遇到问题。这是我从服务器获得的响应。

[{
  "list_name":"list1",
  "list_id":"4",
  "created":"2011-07-07 21:21:16",
  "user_id":"123456"
},
{
  "list_name":"list2",
  "list_id":"3",
  "created":"2011-07-07 21:19:51",
  "user_key":"678901"
}]

这是我的javascript代码......

// Router
App.Routers.AppRouter = Backbone.Router.extend({
    routes: {
        '': 'index'
    },
    initialize: function() {
    },
    index: function() {
        var listCollection = new App.Collections.ListCollection();
        listCollection.fetch({
            success: function() {
                new App.Views.ListItemView({collection: listCollection});
            },
            error: function() {
                alert("controller: error loading lists");
            }
        });
    }
});

// Models
var List = Backbone.Model.extend({
    defaults: {
        name: '',
        id: ''
    }
});

App.Collections.ListStore = Backbone.Collection.extend({
    model: List,
    url: '/lists'
});

// Initiate Application
var App = {
    Collections: {},
    Routers: {},
    Views: {},
    init: function() {
        var objAppRouter = new App.Routers.AppRouter();
        Backbone.history.start();
    }
};

我在Backbone.js的这一行上收到错误“无法将相同的模型添加到两次”

if (already) throw new Error(["Can't add the same model to a set twice", already.id]); 

我检查了Backbone.js注释,发现第一个模型被添加到集合中,但第二个模型给出了这个错误。为什么会这样?我应该更改服务器端响应中的内容吗?

3 个答案:

答案 0 :(得分:8)

您的Listid属性中有defaults,默认情况下每个实例都具有相同的ID,Backbone正在使用它来检测欺骗。如果您的数据使用list_id作为ID,则需要将idAttribute: 'list_id'放在List类定义中,以告知Backbone。

顺便说一下,我更喜欢不在对象属性中复制类型信息(Backbone.js同意这一点)。具有一致的属性名称是骨干所期望的并且更易于使用。因此,不要使用list_idlist_name,而只需在所有类上使用idname

答案 1 :(得分:1)

使用此修复程序添加具有相同ID的模型。

添加时,请使用:collection.add(model,{unique: false})

var __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

Backbone.Collection = (function(_super) {

    __extends(Collection, _super);

    function Collection() {
        return Collection.__super__.constructor.apply(this, arguments);
    }

    Collection.prototype.add = function(models, options) {
        var i, args, length, model, existing;
        var at = options && options.at;
        models = _.isArray(models) ? models.slice() : [models];

        // Begin by turning bare objects into model references, and preventing
        // invalid models from being added.
        for (i = 0, length = models.length; i < length; i++) {
            if (models[i] = this._prepareModel(models[i], options)) continue;
            throw new Error("Can't add an invalid model to a collection");
        }

        for (i = models.length - 1; i >= 0; i--) {
            model = models[i];
            existing = model.id != null && this._byId[model.id];

            // If a duplicate is found, splice it out and optionally merge it into
            // the existing model.
            if (options && options.unique) {
                if (existing || this._byCid[model.cid]) {
                    if (options && options.merge && existing) {
                        existing.set(model, options);
                    }
                    models.splice(i, 1);
                    continue;
                }
            }

            // Listen to added models' events, and index models for lookup by
            // `id` and by `cid`.
            model.on('all', this._onModelEvent, this);
            this._byCid[model.cid] = model;
            if (model.id != null) this._byId[model.id] = model;
        }

        // Update `length` and splice in new models.
        this.length += models.length;
        args = [at != null ? at : this.models.length, 0];
        Array.prototype.push.apply(args, models);
        Array.prototype.splice.apply(this.models, args);

        // Sort the collection if appropriate.
        if (this.comparator && at == null) this.sort({silent: true});

        if (options && options.silent) return this;

        // Trigger `add` events.
        while (model = models.shift()) {
            model.trigger('add', model, this, options);
        }

        return this;
    };

    return Collection;

})(Backbone.Collection);

答案 2 :(得分:0)

Backbone阻止我们将相同的模型插入一个集合中...... 你可以在backbone.js第676行到第700行看到它

如果你真的想要将相同的模型插入到集合中,只需删除那里的代码

    if(existing = this.get(model)){//here
          ...
    }