0

我在 Backbone 中创建了一个视图(列表容器),它应该包含多个视图项(部分),并处理某些事件。这种情况下的问题是,事件的执行频率与子视图项放置在容器内的频率一样高。

我知道如果我将 closeSection 方法放入 Container 视图中,我可以防止这种影响,但我认为这是一个错误的地方,专注于完整的工作视图。

在 Backbone.js 上下文中解决此问题的最佳解决方案是什么?

例子:

// The Container View (simplified)
var Container = Backbone.View.extend({
  el:$('#someDivContainer'),

  render:function(){
    $(this.el).html('<div id="head"></div><div id="sections"></div>');
    return this;
  }
});


// The subview (simplified)
var subView = backbone.View.extend({
  template:_template('<div><div class="scthd"><a class="op_cl">x</a></div><div><%- content %></div></div>');
  events:{
    'click a.op_cl':'closeSection'
  },

  initialize:function(){
    this.setElement($('#sections');
  },

  closeSection:function(event){
    event.preventDefault();
    console.log('event was triggered');
  },


  render:function(){
     $(this.el).append(this.template({content:'Test ' + i});
     return this;
  }
}); 

var oContainer = new Container();
    oContainer.render().el;


 // These produces a ten time event execution by a click on one a.op_cl item
 for(var i=0; i<10; i+=1){
   var oSubView = new subView();
       oSubView.render().el;
 }

“最终”输出类似于以下示例:

<!-- The HTMl of the first view -->
<div id="head"></div>
<div id="sections">
  <div>
    <div class="scthd">
      <a class="op_cl">x</a>
    </div>
    <div>Test 0</div>
  </div>

  <div>
    <div class="scthd">
      <a class="op_cl">x</a>
    </div>
    <div>Test 1</div>
  </div>

  <div>
    <div class="scthd">
      <a class="op_cl">x</a>
    </div>
    <div>Test 2</div>
  </div>

  <div>
    <div class="scthd">
      <a class="op_cl">x</a>
    </div>
    <div>Test n</div>
  </div>
</div>

提前谢谢。

4

2 回答 2

0

要了解您的问题是什么,您首先需要了解在backbone.js 中,当您声明事件哈希时,这些事件被委托给el视图的根。在您的情况下发生的情况是,由于您的所有子视图都使用相同的#sections元素,它们的事件被绑定到相同的元素。

我不确定为什么要将它们设置为相同的元素,因此根据您要执行的操作,您可以省略this.setElement($('#sections'));并让容器视图附加子视图或使用其他方法来附加子视图意见。至于将事件传达给容器视图,您只需在容器视图中声明事件即可。

于 2013-07-30T13:24:10.093 回答
0

您设置视图的方式在概念上是错误的(至少在 Backbone 领域),因为它会导致这些结果。这里的主要错误是让所有子视图共享一个公共根元素。这是非常糟糕的行:

initialize: function() {
    this.setElement($('#sections'));
}

这在概念上是错误的,因为您以相反的方式分配职责。而不是拥有一个Sidebar将使用所有需要的子视图构建自己的根视图,而是让子视图将自己附加到Sidebar.

正如杰克在他的回答中正确所说的那样,这在事件处理方面也存在问题。当你说这样的话:

events: {
    'click a.op_cl': 'closeSection'
}

您正在将单击事件侦听器附加到视图的根元素,当触发时,将首先检查目标是否与选择器匹配,如果是,将执行您的回调。在这种情况下,您将 10 个事件侦听器附加到同一个元素 ( #section) 并且当您单击链接时,每个事件都将匹配并触发。

您应该将您的子视图更改为

var SubView = Backbone.View.extend({

    tagName: 'li',

    template: _template('<div class="scthd"><a class="op_cl">x</a></div><div><%- content %></div>'),

    events: {
        'click a.op_cl': 'closeSection'
    },

    closeSection: function(event) {
        console.log('event was triggered');
    },

    render: function() {
        $(this.el).append(this.template({content:'Test ' + i});
        return this;
    }

});

然后将这些SubView实例附加到Sidebar, 从Sidebar.

于 2013-07-30T14:21:27.123 回答