【问题标题】:Backbone.js: Can't add the same model to a set twiceBackbone.js:不能将相同的模型添加到集合中两次
【发布时间】:2011-07-17 13:16:51
【问题描述】:

我刚刚开始使用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,发现第一个模型被添加到集合中,但第二个模型给出了这个错误。为什么会这样?我应该更改服务器端响应中的某些内容吗?

【问题讨论】:

    标签: javascript backbone.js


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          猜你喜欢
          • 2014-03-23
          • 2012-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-18
          • 2012-09-11
          • 1970-01-01
          相关资源
          最近更新 更多