javascript - 主干 DOM 事件多次触发

标签 javascript jquery backbone.js backbone-events

我是第一次构建主干应用程序 - 进展顺利。

但是,我认为我没有以正确的方式为我的模型集合创建 View ,当我绑定(bind)事件时,它们会为每个 View 触发,而我只希望它们为一个 View 触发。

这是我的 Backbone 代码(片段):

        (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
            }
        ]
    }
];

这是我的 View 模板

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

View 正确组合,但当我单击一个 View 时,事件会在所有 View 上触发。有人可以指出我正确的方向吗?

最佳答案

由于您在 View 的 events 对象中省略了选择器,因此以下情况适用

根据主干 Documentation : 省略选择器会导致事件绑定(bind)到 View 的根元素 (this.el)。

问题是每个 SeriesGridItemViewclick 事件绑定(bind)到 #model-grid 并且每个 View 都是 #模型网格。在您的示例中,您注册了 5 个点击事件,当您点击任何 View 时,将触发所有 5 个事件。

在不更改任何其他代码的情况下,一种解决方案是将您的 events 对象设置为返回一个函数,这样您就可以为每个 View 指定一个 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 指定为所有 View 的根元素。它最终看起来像: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);
});

一个侧面的建议

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

关于javascript - 主干 DOM 事件多次触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18268616/

相关文章:

javascript - Breeze JS/ODATA : Casts can only be performed on entity types

javascript - 回到 iframe 的历史记录,但更改主窗口的地址

javascript - 如何从 json 对象输出一些东西?

JQuery 对话框 ('open' )不工作

javascript - javascript 中特定调用的所有 ajax 回调的一个入口点

javascript - 在 Backbone.js 中使用 Jade 模板

javascript - 确保文本字段以特定值 : jQuery 开头

javascript - Angular 中使用模态窗口进行 Ng 重复和自动完成选择

单个元素上的 Javascript

javascript - 为什么追加一个documentFragment时需要用到cloneNode?