привязка события backbone js view только к элементам представлений

Привет, я изучаю магистраль, и у меня возникают проблемы с привязкой событий к представлениям. Моя проблема в том, что у меня есть конструктор представления, который при вызове связывает все представления с событием нажатия кнопки, которое является только частью одного представления. Я хотел бы, чтобы событие нажатия кнопки было привязано только к 1 представлению, содержащему кнопку.

http://jsbin.com/tunazatu/6/edit?js,console,output

  1. нажмите на все кнопки просмотра
  2. затем нажмите назад, чтобы просмотреть 1
  3. нажмите красную кнопку (все модели представлений console.log их имена)

Итак, я просмотрел код из этого сообщения множественное срабатывание событий, которое показывает что у вас может быть несколько представлений с одним и тем же тегом el через tagName, но отображать события только на их html-элементы. Это также то, что сделано в примере localtodos от Jérôme Gravel-Niquet.

Я также пытался не объявлять el /tunazatu/7/edit?js,console,output, но тогда кажется, что никакое событие не связано.


    var AppView = Backbone.View.extend({
    tagName:"div",  //tagName defined
    getName:function(){
      console.log(this.model.get('name'));
    },
    initialize:function(options){
      this.listenTo(this.model, 'change', this.render);
      var temp_mapper = {appView1:'#route1',appView2:'#route2',appView3:'#route3'};
      var m_name = this.model.get('name');
      this.template = _.template($(temp_mapper[m_name]).html());  //choose the correct template
    },
    render:function(){
      var temp = this.template(this.model.toJSON()); //populate the template with model data
      var newElement = this.$el.html(temp);  //put it in the view's tagName
      $('#content').html(newElement);
    },
    events:{
      "click button":"log"
    },
    log:function(){
      this.getName();
    }
  });

person mbow    schedule 20.05.2014    source источник


Ответы (1)


Ваша проблема в том, что ваш AppView действительно выглядит так:

var AppView = Backbone.View.extend({
    el: "#content",
    //...

Каждый раз, когда вы создаете новый AppView, вы привязываете другой делегатор событий к #content, но никогда не удаляете эти делегирования. Если вы создадите три AppView, вы получите три представления, слушающие click button внутри #content.

Я бы рекомендовал две вещи:

  1. Не пытайтесь повторно использовать представления, создавайте и уничтожайте их (через View#remove) по мере необходимости. Представления должны быть достаточно легкими, чтобы их сборка и разборка были дешевыми.
  2. Не привязывайте несколько представлений к одному и тому же el. Вместо этого позвольте каждому представлению создать свой собственный el, а затем позвольте вызывающему объекту поместить это el внутри некоторого контейнера.

Если вы сделаете обе эти вещи, ваша проблема исчезнет. Ваш AppView будет выглядеть примерно так:

var AppView = Backbone.View.extend({
  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this; // Common practise, you'll see why shortly.
  },
  // As you already have things...
});

Тогда ваши методы маршрутизатора будут выглядеть примерно так:

view1: function() {
  if(this.appView)
      this.appView.remove();
  this.appView = this.createView('appView1');
  $('#content').html(this.appView.render().el);
  // that `return this` is handy ----------^^
},

Если вы должны придерживаться своего текущего подхода, вам придется вызвать undelegateEvents для текущего AppView, прежде чем вы визуализировать еще один и delegateEvents на новом AppView после его рендеринга.

Но на самом деле, не бойтесь уничтожать представления, которые вам не нужны в данный момент: уничтожайте все представления, которые вам не нужны на странице прямо сейчас, и создавайте новые экземпляры, когда они вам понадобятся. Бывают случаи, когда вы не хотите разрушать свои взгляды, но обычно этого можно избежать.

person mu is too short    schedule 20.05.2014
comment
спасибо за ответ, который действительно помог мне задать дополнительный вопрос: когда вы сказали это Не привязывайте несколько представлений к одному и тому же эл. Вместо этого позвольте каждому представлению создать свой собственный el, а затем позвольте вызывающему объекту поместить этот el в некоторый контейнер. Если вам нужно прикрепить события jquery, как лучше всего сделать это из области действия вызывающего объекта? - person mbow; 21.05.2014
comment
Как правило, вам не следует вручную привязывать события jQuery, вместо этого вы почти всегда можете использовать объект events в соответствующем представлении. Имейте в виду, что delegateEvents использует форму делегирования jQuery on, поэтому элементы не должны существовать при создании el; если вам приходится иметь дело с не всплывающими событиями, вы можете использовать this.$(...), чтобы найти элементы для привязки, а затем отменить привязку в переопределении View#remove. - person mu is too short; 21.05.2014