2013-08-16 53 views
3

嗨,大家好我是第一次构建骨干应用程序 - 它的进展很好!多次发射骨干DOM事件

但是,我不认为我是以正确的方式为我的模型集合创建视图,并且当我绑定的事件是为每个视图触发时,我只希望它们为一个视图启动。

这里是我的骨架代码(片段):

 (function(){ 

     Series = Backbone.Model.extend({ 
      defaults:{ 
       active:false 
      } 
     }); 

     SeriesGridItemView = Backbone.View.extend({ 
      el:'#model-grid', 
      defaults: { 
       active : false 
      }, 
      initialize: function(){ 
       this.render(); 
       this.listenTo(this.model, 'change', this.setState); 
      }, 
      render: function(){ 
       this.template = _.template($('#template-model-grid-item-view').html()); 
       this.view = $(this.template(this.model.toJSON())).appendTo(this.$el); 
      }, 
      setState: function(){ 
       this.active = this.model.get('active'); 
       this.view.toggleClass('active',this.active); 
      }, 
      events: { 
       'click':'toggle' 
      }, 
      toggle: function(e){ 
       e.stopPropagation(); 
       e.preventDefault(); 
       console.log('clicked'); 
       return false; 
      } 

     }); 

     SeriesCollection = Backbone.Collection.extend({ 
      model: Series, 
      setPrice : function(p){ 
       this.forEach(function(m){ 
        var active = 0; 
        _.each(m.get('vehicles'),function(v){ 
         if(v.price <=p){ 
          v.active = true; 
          active++; 
         } 
         else{ 
          v.active = false; 
         } 
        }); 
        m.set('active',active>0); 
       }); 
      } 
     }); 

     series = new SeriesCollection(window.BMW.data.series); 
     series.forEach(function(m,i){ 
      var c = i+1; 
      if(c > 3){ 
       c%=3; 
      } 
      m.set('column','1'); 
      new SeriesGridItemView({model:m}); 
     }); 
    })(); 

这里是构建模型的JSON:

window.BMW.data.series = [ 
    { 
     seriesId:1, 
     name:'1 Series', 
     slug:'1-series', 
     order:0, 
     vehicles:[ 
      { 
       seriesId:1, 
       price:200 
      }, 
      { 
       seriesId:2, 
       price:300 
      } 
     ] 
    }, 
    { 
     seriesId:2, 
     name:'3 Series', 
     slug:'3-series', 
     order:1, 
     vehicles:[ 
      { 
       seriesId:1, 
       price:400 
      }, 
      { 
       seriesId:2, 
       price:500 
      } 
     ] 
    }, 
    { 
     seriesId:3, 
     name:'4 Series', 
     slug:'4-series', 
     order:3, 
     vehicles:[ 
      { 
       seriesId:1, 
       price:100 
      }, 
      { 
       seriesId:2, 
       price:300 
      } 
     ] 
    }, 
    { 
     seriesId:4, 
     name:'6 Series', 
     slug:'6-series', 
     order:4, 
     vehicles:[ 
      { 
       seriesId:1, 
       price:100 
      }, 
      { 
       seriesId:2, 
       price:300 
      } 
     ] 
    }, 
    { 
     seriesId:6, 
     name:'X3', 
     slug:'x3', 
     order:5, 
     vehicles:[ 
      { 
       seriesId:1, 
       price:500 
      }, 
      { 
       seriesId:2, 
       price:800 
      } 
     ] 
    } 
]; 

这里是我的意见模板

<script type="text/template" id="template-model-grid-item-view"> 
    <div id="series-<%=seriesId%>" class="grid-item-view column-<%=column%>"> 
     <div class="label"><%= name %></div> 
     <div class="thumbnail"> 
      <img src="/Content/themes/BMW/img/series/small/<%= slug %>.png"/> 
     </div> 
    </div> 
</script> 

问题 - 视图可以正确组装,但当我点击一个视图时,事件在所有视图上触发!有人可以请指点我正确的方向吗?

感谢,

杰克

回答

5

既然你在你的意见你events对象省略选择以下适用

每骨干DocumentationOmitting the selector causes the event to be bound to the view's root element (this.el).

的问题是每个SeriesGridItemView的绑定click事件到#model-grid和每个视图是的孩子。在你的例子中,你注册了5个点击事件,当你点击你的任何视图时,所有5个事件都被触发。

在不更改任何其他代码的情况下,一种解决方案是设置events对象以返回一个函数,以便您可以为每个视图指定一个id选择器。

events: function() { 
    var selector = '#series-' + this.model.get('seriesId'); // this id corresponds to your template id 
    var ev = {}; 
    ev['click ' + selector] = 'toggle'; 
    return ev; 
}, 

另一种选择和我喜欢的选择是不指定#model-grid作为您所有视图的根元素。它最终会看起来像:demo

SeriesGridItemView = Backbone.View.extend({ 
    // remove the following line 
    el:'#model-grid', 

    // .. all else is the same ../ 
}); 

series = new SeriesCollection(window.BMW.data.series); 
    series.forEach(function(m,i){ 
    var c = i+1; 
    if(c > 3){ 
     c%=3; 
    } 
    m.set('column','1'); 
    $('#model-grid').append(new SeriesGridItemView({model:m}).el); 
}); 

A面suggetion

  1. 在你render功能,就没有必要创建变量,您可以通过使用$访问你的元素:

    render: function(){ 
        this.template = _.template($('#template-model-grid-item-view').html()); 
        this.$el.append(this.template(this.model.toJSON()))); 
    }, 
    setState: function(){ 
        this.active = this.model.get('active'); 
        this.$el.toggleClass('active',this.active); 
    }, 
    
+0

谢谢你,我的朋友!这很棒。我爱StackOverflow! – JackMahoney