Backbone DOM事件多次触发 [英] Backbone DOM events firing multiple times

查看:92
本文介绍了Backbone DOM事件多次触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好我是第一次建立一个骨干应用程序 - 它很棒!

Hi guys I'm building a backbone app for the first time - and its going great!

但是,我认为我没有为我创建视图以正确的方式收集模型,当我绑定事件时,我们只为每个视图触发它们。我只希望它们为一个视图开火。

However, I don't think I am creating views for my collection of models in the correct way and when I bind events they fire for every view when I only want them to fire for one.

这是我的骨干代码(一个片段) ):

Here is my backbone code (a snippet):

        (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:

And here is the JSON that constructs the models:

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>

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

The problem - the views assemble correctly but when I click one view the event fires on all of the views! Can someone please point me in the right direction?

谢谢,

杰克

推荐答案

由于您在视图的 events 对象中省略了选择器,因此适用

Since you omitted the selector in your events object of your views the following applies

根据骨干文档
省略选择器会导致事件绑定到视图的根元素(this.el)。

问题是每个 SeriesGridItemView 的bind 点击事件到#model-grid 并且每个视图都是#model-grid 的子视图。在您的示例中,您注册了5个单击事件,当您单击任何视图时,将触发所有5个事件。

The problem is each of the SeriesGridItemView's bind click events to #model-grid and each view is a child of #model-grid. In your example, you register 5 click events and when you click on any of your views, all 5 events are triggered.

在不更改任何其他代码的情况下,一个解决方案是设置事件对象以返回一个函数,这样你就可以了可以为每个视图指定 id 选择器。

Without changing any of your other code, one solution is to setup you events object to return a function so you can specify an id selector for each of your views.

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 作为所有视图的根元素。最终看起来像:演示

Another option and the one I prefer, is to not specify #model-grid as your root element for all your views. It would end up looking like: 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 side suggetion

A side suggetion


  1. render 函数中,无需创建变量,可以使用 $

  1. In your render function, there's no need to create variable, you can access your element by using $:

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);
},


这篇关于Backbone DOM事件多次触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆