我有一个骨干视图,其中包含各种研究项目的项目数据。
在这个视图中,我有一个按钮,当点击它时,它会执行一个名为&to; toggleChildView'的方法。此方法将子视图插入主页面。
在子视图中,我正在监听用户点击页面上任何位置的事件,但包含研究子评论的元素除外。
问题是,如果我关闭子视图,子视图实际上仍然在某处停留,因为事件仍在触发,并且如果我打开并关闭了子视图,则会多次触发。
因此,例如,如果我打开并关闭子视图5次,在最后关闭后,该事件仍将触发5次。
但是如果关闭它就不应该开火,而且只有在打开时才开火。
我认为我的问题最好这样说:
无论如何都要摆脱孤儿"子视图并确保一次只打开一个子视图?
谢谢!
Parent View:
toggleChildView: function (e) {
this.$('.displayresearchdata').toggle();
this.$('.editdata').toggle();
//initialize the research view into our main view
var researchView = new researchView({ parent: this });
self.$('.research').append(researchView.render().$el);
},
saveresearchdata: function (e) {
this.model.save('researchData', this.$(".researchData").html());
},
Child render method:
initialize: function (options) {
this.parent = options.parent;
},
render: function () {
var self = this;
this.$el.append(this.template());
$("body").on("click", function (event) {
if (!$(event.target).closest('.editdata').length) {
if (self.parent.$('.editdata').is(":visible")) {
self.parent.saveresearchdata();
}
}
});
return this;
},
答案 0 :(得分:1)
由于@mu太短指出,你需要明确地删除()你添加的任何视图。
如果该视图添加了一些自定义事件侦听器,您也应该删除它们。如果您使用事件监听的view.listenTo(target, "eventname", this.functionName)
风格,那么当您调用view.remove()
时,由于调用stopListening()
方法,这些事件处理程序将自动删除。
在您的代码中,问题在于您没有保留对您要添加的子视图的引用,因此您无法在其上调用remove
。保持父母对孩子的内部引用,如:
//initialize the research view into our main view
if(this._researchView) {
this._researchView.remove();
}
this._researchView = new researchView(...)
this.$(".research").empty().append(this._researchView.render().$el);
如果您不想添加许多researchViews,请在添加之前记下empty
的使用情况,一次只能添加一个。如果你确实需要很多视图,那么你可以删除它,并将内部引用保留为数组。
答案 1 :(得分:1)
处理所谓的“僵尸”视图是使用Backbone最棘手的部分之一,如果你有很多子视图,如果你没有正确管理视图,它可能会成为一个真正的问题。关于该主题的开创性帖子是this one by Derrik Bailey,但请注意,他引用的某些方法(例如bind
)现已弃用,以支持listenTo
@CharlieBrown的回答将会成功。但是,如果您打算创建其他视图和/或子视图,可以通过以下方式进行更大规模的设置:
1)创建一个Baseview,从中扩展所有其他视图。
var BaseView = Backbone.View.extend({
//typical initialize and render functions
//...
//Create the close method
close: function () {
if (this.onClose) this.onClose(); //looks for an onClose method in your subviews
this.undelegateEvents();
this.$el.off();
this.$el.children().remove();
this.$el.empty();
this.stopListening();
}
});
2)现在在Backbone路由器中,您可以创建一个trackView
函数,该函数将从基本视图中调用close()
方法
//within router
trackView: function (next) {
console.log('now closing ' + next.cid);
if (this.current) this.current.close();
this.current = next;
},
3)现在应该在trackview
内调用路由器中的所有其他视图,如下所示:
//within router
someView: function () {
console.log('loading create user page');
this.trackView(new someView()); //use trackView from step 2
},
4)最后,在任何子视图中,请确保添加'onClose()'方法,您可以使用从close
继承的Baseview
方法关闭任何潜在的僵尸:< / p>
//inside a view
onClose: function() {
if (this.couldBeAZombieView) this.couldBeAZombieView.close();
}
现在您正在设置更复杂的网站。还有其他方法来设置它,但这是我熟悉的。