Подтвердить что ты не робот

Делегирование событий в под-представлениях в Backbone.js

Мы все знаем, что делать что-то вроде этого плохо:

<ul>
  <li>Item</li>
  <li>Item</li>
  ... 500 more list items
</ul>

а затем...

$("ul li").bind("click", function() { ... });

Я просматривал много примеров/руководств по базовым сценариям, и, похоже, это стандартный подход к рендерингу списка элементов, основанный на коллекции моделей.

var ListView = Backbone.View.extend() {

  tagName: 'ul',

  render: function() {
    this.collection.each(function(item) {
      var view = new ListItemView({model: item});
      $(this.el).append(view.render().el);
    });
    return this;
  }
});

Просмотр элемента списка:

var ListItemView = Backbone.View.extend() {

  tagName: 'li',

  events: {
   'click' : 'log'
  }

  log : function() {
    console.log(this.model.get("title"));
  }

  render: function() {
    $(this.el).html(this.template(this.model.toJSON()));
    return this;
  }
});

Если я не ошибаюсь, создание экземпляра listView с помощью коллекции с 500 моделями дает мне 500 событий щелчка, по одному для каждой строки. Это плохо?

Я знаю, что Backbone построил делегирование событий для событий с именами:

events : {
  'click li' : 'log'
}

Я предполагаю, что могу поместить это в свой ListView, и он создаст только одно событие click для всего списка, но тогда я не смогу получить доступ к данным модели, соответствующим элементу с щелчком.

Какие шаблоны используют базовые разработчики для решения этой типичной проблемы?

4b9b3361

Ответ 2

Следить за просмотром подпунктов из родительского представления. Затем, добавляя subview, добавьте его в хеш, а также добавьте cid к элементу subview. Этот способ имеет указатель на подвью и может выполнять операции над его моделью и т.д.

Я не тестировал этот точный код ниже, так что это может быть неправильно в месте или двух, но я проверил этот общий принцип. Я также пропустил код listitemview.

var ListView = Backbone.View.extend() {
  subViews: {},
  tagName: 'ul',
  events: {
    'click li' : 'clickItem'
  },
  clickItem: function(event){
     var id = event.currentTarget.cid;
     var subView = this.subViews[id];


  },
  render: function() {

    this.collection.each(function(item) {
      var view = new ListItemView({model: item});
      this.subViews[view.cid] = view;
      subEl = view.render().el;
      subEl.cid = view.cid;
      $(this.el).append(subEl);
    });
    return this;
  }
});

Ответ 3

Вы можете связать экземпляр с таким элементом:

events : {
  'click li' : 'log'
},

log: function( e ) {
var elm = e.currentTarget //Same as `this` in normally bound jQuery event


jQuery.data( elm, "viewInstance" ).log( e );
},

Тогда:

var ListItemView = Backbone.View.extend() {

  tagName: 'li',

  log : function() {
    console.log(this.model.get("title");
  }

  render: function() {
        //Associate the element with the instance
    $(this.el).html(this.template(this.model.toJSON())).data( "viewInstance", this );
    return this;
  }
});