我的路由器中有addPost
个功能。每次调用函数时我都不想重新创建postAddView
:
addPost: function () {
var that = this;
if (!this.postAddView) {
this.postAddView = new PostAddView({
model: new Post()
});
this.postAddView.on('back', function () {
that.navigate('#/post/list', { trigger: true });
});
}
this.elms['page-content'].html(this.postAddView.render().el);
}
这是PostAddView:
PostAddView = backbone.View.extend({
events: {
'click #post-add-back': 'back'
}
, back: function (e) {
e.preventDefault();
this.trigger('back');
}
});
第一次渲染postAddView时,事件触发器运行良好。但是,在将其他视图渲染到page-content
并渲染postAddView
之后,事件触发器将不再触发。以下版本的addPost
效果很好。
addPost: function () {
var that = this, view;
view = new PostAddView({
model: new Post()
});
this.elms['page-content'].html(view.render().el);
view.on('back', function () {
delete view;
that.navigate('#/post/list', { trigger: true });
});
}
答案 0 :(得分:2)
你正在某个地方调用jQuery的remove
和那个
除了元素本身之外,还删除了与元素关联的所有绑定事件和jQuery数据。
因此,Backbone用于将事件绑定到postAddView.el
的{{3}}调用将会丢失。然后,当您重新添加postAddView.el
时,不再有delegate
附加,也不会触发任何事件。请注意,Backbone.View的标准delegate
方法调用jQuery的remove
; jQuery中的一些其他内容,就像remove
将对事件处理程序执行类似的操作一样。因此,杀死delegate
的实际函数调用可能隐藏在其他内容中。
您可以尝试手动调用empty
:
this.elms['page-content'].html(this.postAddView.render().el);
this.postAddView.delegateEvents();
或者更好,只需抛开视图并在每次需要时创建一个新视图。您的视图对象应该非常轻,因此创建新视图对象应该比手动跟踪现有视图更便宜且更轻松。
答案 1 :(得分:1)
如果你真的想重用当前的DOM和View,你不需要像你一样一次又一次地设置元素,你调用.html()
的所有内容都会破坏视图的DOM并再次生成和失去的事件。另外,我更喜欢在呈现视图之前在DOM中添加“el”。我将以这种方式拥有你的功能:
addPost: function () {
if (!this.postAddView) {
this.postAddView = new PostAddView({
model: new Post()
});
this.postAddView.on('back', this.onBack);
this.elms['page-content'].html(this.postAddView.el);
}
this.postAddView.render();
},
onBack : function () {
this.navigate('#/post/list', { trigger: true });
}
我不喜欢使用局部变量来引用“this”。如果所有视图在初始化方法中都使用_.bindAll(this)
,您可以将事件绑定到视图中并使用它(检查我如何转换onBack)。
使用我的代码,无需手动调用this.delegateEvents()