using a single div as a container for multiple backbone views losing event bindings

时光总嘲笑我的痴心妄想 提交于 2019-12-05 10:45:29

When you use .html(dom_object):

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

You're actually doing this:

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

and empty:

removes other constructs such as data and event handlers from the child elements before removing the elements themselves [To avoid memory leaks]

So once you've added, say, widgets_view to #current_tab and then .html(this.foobars_view.el), the events on widgets_view.el are gone. Your .html call works fine the first time because there's nothing in #current_tab so there aren't any events to unbind.

You can use your "reuse the views" approach by adding simple delegateEvents calls into the mix to rebind the events:

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
}

While I'm here, you can use this.$('#current_tab') instead of $(this.el).find('#current_tab') and this.$el instead of $(this.el).

Demo: http://jsfiddle.net/ambiguous/75KuW/1/

Note that switching tabs in the above preserves the content of the <input type="text"> elements. If you don't need that sort of behavior then you're probably better off removing and instantiating views as needed instead of holding all the views and swapping them in and out.

Also, if your WidgetsView (and friends) have other Backbone views inside them, you'll have to call delegateEvents on the contained views all the way down. In this case, some sort of bind_events method on the views would make sense:

this.widgets_view.rebind_events(); // delegateEvents() all the way down this view subtree
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!