Javascript 主干视图:delegateEvents未将事件重新绑定到子视图
我已经将这个问题分解为尽可能小的示例(即,它只是为了演示问题,而不一定代表真实世界的场景) 假设我有一个父视图(此处为“MainView”),其中包含一个子视图(此处为“SubView”)。如果在任何时候,我需要重新呈现父视图(从而重新呈现子视图),我将丢失子视图中的事件绑定,尽管调用了Javascript 主干视图:delegateEvents未将事件重新绑定到子视图,javascript,jquery,backbone.js,Javascript,Jquery,Backbone.js,我已经将这个问题分解为尽可能小的示例(即,它只是为了演示问题,而不一定代表真实世界的场景) 假设我有一个父视图(此处为“MainView”),其中包含一个子视图(此处为“SubView”)。如果在任何时候,我需要重新呈现父视图(从而重新呈现子视图),我将丢失子视图中的事件绑定,尽管调用了delegateEvents 可以在以下位置找到JSFIDLE: 以下是完整的代码: var MainView = Backbone.View.extend({ tagName : "div",
delegateEvents
可以在以下位置找到JSFIDLE:
以下是完整的代码:
var MainView = Backbone.View.extend({
tagName : "div",
initialize : function() {
this.subView = new SubView();
},
render : function() {
this.$el.html(this.subView.render().$el); // .html() breaks binds
this.subView.delegateEvents(); // this re-establishes them
return this;
}
});
var SubView = Backbone.View.extend({
tagName : "div",
events : {
"click .button1" : "onButtonPress"
},
onButtonPress : function() {
alert("Button pressed");
},
render : function() {
var html = "<button class='button1'>Button1</button>";
this.$el.html(html);
return this;
}
});
var v = new MainView();
$("#area1").html(v.render().$el); // binds work fine
// do some work... then re-render...
$("#area1").html(v.render().$el); // breaks event binds
var MainView=Backbone.View.extend({
标记名:“div”,
初始化:函数(){
this.subView=新建子视图();
},
render:function(){
this.$el.html(this.subView.render().$el);//.html()中断绑定
this.subView.delegateEvents();//这将重新建立它们
归还这个;
}
});
var SubView=Backbone.View.extend({
标记名:“div”,
活动:{
单击按钮1:“按按钮按”
},
onButtonPress:function(){
警报(“按下按钮”);
},
render:function(){
var html=“Button1”;
这个.$el.html(html);
归还这个;
}
});
var v=新的主视图();
$(“#区域1”).html(v.render().$el);//他工作得很好
//做一些工作。。。然后重新渲染。。。
$(“#区域1”).html(v.render().$el);//中断事件绑定
我不明白为什么会这样。任何输入都将不胜感激。要保留绑定,您可以做三件事 使用$.append而不是$.html 使用
$.append
将保持绑定的完整性,并注意不要丢失任何兄弟内容
只需重新渲染而无需重新附加
在代码中,您可以重新呈现视图并重新附加其内容。这是没有必要的。只需调用v.render()
即可获得相同的视觉效果,但保持绑定完好无损
var v = new MainView();
$("#area1").html(v.render().$el); // binds work fine
// do some work... then re-render…
v.render(); // keeps event binds
$("#area1").append(v.render().$el); // works too
在调用$.html()之前使用$.empty()
根据
如果保留对这些DOM元素的引用并且需要它们保持不变,请使用.empty().html(字符串)而不是.html(字符串),以便在将新字符串分配给元素之前从文档中删除这些元素
重要的一点是,$.html需要一个html字符串,而不是元素,并且还取消绑定子节点上的任何事件处理程序。我能解释这种行为的唯一方法是,通过将dom树转换为字符串,或者反过来,事件被删除。有趣的是,使用文档中提到的$.empty()可以解决这个问题
// any $.html reference needs to have an $.empty too
this.$el.empty().html(this.subView.render().$el);
// and then later for your mainView
$("#area1").empty().html(v.render().$el);
谢谢你的建议。我避免使用
append
,因为它强制javascript指定元素的顺序。至于第二个建议,虽然这在本例中有效,但如果MainView
本身是另一个父视图的子视图,则不起作用。JSFIDLE:我更新了我的答案,参考了jQuery文档和$.html
的工作解决方案。那很有趣。我注意到jQuery文档提到,只有IE中的文本内容损坏才需要这样的步骤,但这个问题似乎发生在每个浏览器上(不管怎样,我到目前为止测试过的所有浏览器)。我想知道这个问题是:(a)未被记录的预期行为,还是(b)使用另一个问题的解决方案发现了解决方法的意外行为。感谢您的解决方案并解释了.html()
的jquery陷阱,很高兴了解它!