我有一个骨干视图,其中包含各种研究项目的项目数据。
在这个视图中,我有一个按钮,当单击它时,它会执行一个名为“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;
},发布于 2014-09-09 01:18:30
正如@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);在追加之前注意empty的使用,如果你不想添加很多researchViews,一次只添加一个。如果你确实想要很多视图,那么你可以删除它,并将内部引用保留为一个数组。
发布于 2014-09-09 17:39:39
处理所谓的“僵尸”视图是使用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)现在,在您的骨干路由器中,您可以创建一个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()‘方法,在该方法中,您可以使用从Baseview继承的close方法关闭任何潜在的僵尸
//inside a view
onClose: function() {
if (this.couldBeAZombieView) this.couldBeAZombieView.close();
}现在,您已经为一个更复杂的站点进行了设置。还有其他方法可以设置,但这是我熟悉的方法。
https://stackoverflow.com/questions/25728168
复制相似问题