Странное поведение с этим в Backbone.js при привязке к добавлению/удалению в коллекции

У меня есть следующие два представления, основанные на Backbone.js.

pg.views.ItemList = Backbone.View.extend({

  tagName:  "div",
  className: "items",

  initialize: function() {
    _.bindAll(this, 'addOne', 'addSelected')

    Items.bind('add',     this.addOne);

    Items.fetch();
  },

  // REMOVED

  addOne: function(Item) {
    console.log($(this.el));
    var view = new pg.views.Item({model: Item});
    $(this.el).append(view.render().el);
  },

  addSelected: function(ItemList) {
    _.each(ItemList, this.addOne);
    return this.el;
  },

  // REMOVED

});

pg.views.Section = Backbone.View.extend({

  tagName:  "section",

  sectionTemplate: _.template($('#section-template').html()),

  events: {
    // REMOVED
  },

  initialize: function() {
    _.bindAll(this, 'render', 'close', 'addItemToSection', 'removeItemFromSection');
    this.model.bind('change', this.render);
    this.model.view = this;

    Items = new pg.collections.ItemList;
  },

  render: function() {
    $(this.el).html(this.sectionTemplate(this.model.toJSON()));
    this.setContent();
    Items.bind('add', this.addItemToSection);                   // "add" event bind
    Items.bind('remove', this.removeItemFromSection);           // "remove" event bind
    this.addItems();
    return this;
  },

  addItems: function() {
    var ids = this.model.get('items');
    var view = new pg.views.ItemList;
    var items = _.map(ids, function(id){ return Items.get(id); });
    $(this.el).append(view.addSelected(items));
  },

  // FUNCTIONS REMOVED

  setContent: function() {
    var title = this.model.get('title');
    this.$('.title').text(title);
    this.title = this.$('.title-input');
    this.title.val(title);
  },

  addItemToSection: function(Item) {
    console.log(this.model.get('title'));
    // REMOVED
  },

  removeItemFromSection: function(Item) {
    console.log(this.model.get('title'));
    // REMOVED
  }

});

Вот проблема, с которой я сталкиваюсь.

У меня есть представление, в котором пользователь создает два раздела, скажем, они называются «раздел1» и «раздел2». Эти имена используются в атрибуте title.

Вот какое странное поведение я наблюдаю:

  1. Когда пользователь находится в «разделе 1» и добавляет элемент, запускается событие привязки «добавить», в результате чего в консоль записывается «раздел 2».

  2. Когда пользователь находится в «разделе 1» и добавляет элемент, запускается событие привязки «удалить», в результате чего «раздел 1» записывается в консоль.

  3. Когда пользователь находится в «разделе 2» и добавляет элемент, запускается событие привязки «добавить», в результате чего «раздел 2» записывается в консоль.

  4. Когда пользователь находится в «разделе 2» и добавляет элемент, запускается событие привязки «удалить», в результате чего в консоль записывается «раздел 2», а затем «раздел 1».

Если я привязываю «добавить» внутри представления «pg.views.Section», используя «this.addItemToSection», разве он не должен вызывать только блок «addItemToSection» внутри этого экземпляра?

Единственная строка, которую я вижу, «переопределяет» «это», - это привязка «добавить» в блоке инициализации «pg.views.ItemList». Если эта строка является виновником, как мне предотвратить переопределение «этого» в привязке «добавить» для «раздела 1»?


person Andrew De Andrade    schedule 30.11.2010    source источник
comment
Я предполагаю, что ваш вопрос немного неясен. Можете ли вы воспроизвести ошибку в отдельном примере? Может быть, разместить этот пример в Интернете, чтобы мы могли посмотреть?   -  person Julien    schedule 13.12.2010
comment
Одна вещь, которая выглядит неправильно, это то, что вы вызываете Items.bind вместо this.bind в нескольких местах.   -  person Sam    schedule 03.05.2011


Ответы (1)


Я думаю, что это глобальная проблема, каламбур;) Вы вызываете все в Items, которое сначала было объявлено с помощью var - (плохая практика) подразумевает, что оно будет привязано к объекту окна. И вы используете ту же ссылку на переменную в другом представлении! Таким образом, оба получат вызов, потому что они относятся к одному и тому же объекту!!!! Вы можете иметь столько «локальных» экземпляров, сколько хотите, привязавшись к «этому». Попробуйте следующие изменения, я думаю, они должны работать.

pg.views.ItemList = Backbone.View.extend({

  tagName:  "div",
  className: "items",

  initialize: function() {
    _.bindAll(this, 'addOne', 'addSelected')

    this.myItems = new pg.collections.ItemList(); //create local reference

    this.myItems.bind('add', this.addOne);

    this.myItems.fetch();
  },

  ...    
});

pg.views.Section = Backbone.View.extend({

  tagName:  "section",


  initialize: function() {
    _.bindAll(this, 'render', 'close', 'addItemToSection', 'removeItemFromSection');
    this.model.bind('change', this.render);
    this.model.view = this;

    this.mySectionItems = new pg.collections.ItemList; //add to 'this'
  },

  render: function() {
    $(this.el).html(this.sectionTemplate(this.model.toJSON()));
    this.setContent();
    this.mySectionItems.bind('add', this.addItemToSection);         // "add" event bind
    this.mySectionItems.bind('remove', this.removeItemFromSection); // "remove" event bind
    this.addItems();
    return this;
  },
...

});
person PhD    schedule 18.08.2011