5

好的,所以我有一个导航和仪表板的概念。在我的路由器中,当我单击导航链接时,我正在调用我的仪表板视图来设置活动选项卡。

例如:

资产净值

<a href="#" class="dashabord_tab" id="widgets">Widgets</a>
<a href="#" class="dashabord_tab" id="Foobars">Foobars</a>

dashboard_container.jst.tpl

<div id="nav"></div>
<div id="current_tab"></div>

仪表板视图

DashboardView = Backbone.View.extend({
  template:JST.dashboard_container,
  render: function(){
    $(this.el).html(this.template());
  },
  activateWidgets: function(){ 
    if(!(this.widgets_view)){
      this.widgets_view = new WidgetsView();
      this.widgets_view.render();
    }
    $(this.el).find("#current_tab").html(this.widgets_view.el);
  }, 
  activateFoobars: function(){ 
    if(!(this.foobars_view)){
      this.foobars_view = new FooBarsView();
      this.foobars_view.render();
    }
    $(this.el).find("#current_tab").html(this.foobars_view.el);
  }
});

问题:

因此,当我第一次切换到 widgets_tab 或 foobar_tab 时,选项卡会按预期加载。但是,如果我切换到一个选项卡,退出它,然后切换回它,我视图中的所有事件都不再绑定。单击,悬停,例如 foobars_view 内的所有视图都不是可单击、可悬停等。

过去,我一直在为每个子视图制作一个包装器,如下所示:

过去的解决方案,皮塔:

activateFoobars: function(){ 
    $('.tab_wrapper').hide();
    if($(this.el).find("#foobars_wrapper").length < 1){
      $(this.el).append("<div class='tab_wrapper' id='foobars_wrapper'></div>");
      this.foobars_view = new FooBarsView();
      $(this.el).find("#foobars_wrapper").html(this.foobars_view.render().el);
    }
  $('#foobars_wrapper').show();
  }

我宁愿不按照上面显示的方式进行操作,而且我真的很喜欢将视图的 el 放在始终保持打开状态的 active_tab div 中的想法……如果我不能按照我想要的方式进行操作to,有没有替代我刚才展示的方式?谢谢!

4

1 回答 1

5

当你使用.html(dom_object)

$(this.el).find("#current_tab").html(this.widgets_view.el);

你实际上是这样做的:

$(this.el).find('#current_tab').empty().append(this.widgets_view.el);

empty

在删除元素本身之前从子元素中删除其他构造,例如数据和事件处理程序 [避免内存泄漏]

因此,一旦您添加了widgets_viewto#current_tab和 then .html(this.foobars_view.el),on 上的事件就widgets_view.el消失了。您的.html通话第一次运行良好,因为没有任何内容,#current_tab因此没有任何事件可以解除绑定。

delegateEvents您可以通过在混合中添加简单的调用来重新绑定事件,从而使用您的“重用视图”方法:

activateWidgets: function(){ 
  if(!(this.widgets_view)){
    this.widgets_view = new WidgetsView();
    this.widgets_view.render();
  }
  $(this.el).find("#current_tab").html(this.widgets_view.el);
  this.widgets_view.delegateEvents(); // <--------------- you need this
}

当我在这里时,您可以使用this.$('#current_tab')代替$(this.el).find('#current_tab')this.$el代替$(this.el).

演示:http: //jsfiddle.net/ambiguous/75KuW/1/

请注意,上面的切换选项卡会保留元素的<input type="text">内容。如果您不需要这种行为,那么您最好根据需要删除和实例化视图,而不是保留所有视图并将它们换入和换出。

此外,如果您WidgetsView(和朋友)在其中有其他 Backbone 视图,则您必须一直调用delegateEvents包含的视图。在这种情况下,视图上的某种bind_events方法是有意义的:

this.widgets_view.rebind_events(); // delegateEvents() all the way down this view subtree
于 2012-05-22T19:28:34.487 回答