不能将同一个模型添加到一个集合中两次

Backbone.js: Can't add the same model to a set twice

本文关键字:一个 集合 两次 同一个 模型 添加 不能      更新时间:2023-09-26

我刚刚开始使用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注释,发现第一个模型被添加到集合中,但第二个模型给出了这个错误。为什么会发生这种情况?我应该在服务器端响应中改变一些东西吗?

您的List在其defaults属性中具有id,这使得每个实例在默认情况下具有相同的ID,并且Backbone使用它来检测副本。如果您的数据使用list_id作为ID,您需要通过将idAttribute: 'list_id'放入List类定义中来告诉Backbone。

作为题外话,我更喜欢不要在对象属性中重复类型信息(并且Backbone.js同意这一点)。具有一致的属性名称是backbone所期望的,并且更容易使用。所以不用list_idlist_name,只要在所有类上使用idname就可以了。

使用此修复添加具有相同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);

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

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

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