我现在大部分时间都在尝试调试我的 Backbone 多页面应用程序以摆脱“僵尸”,但不幸的是没有成功。在今天之前,我什至没有意识到我有一个僵尸问题。我做错了什么?
这是我的区域经理:
var regionManager = (function() {
var currView = null;
var rm = {};
var closeView = function(view) {
if (view && view.close) {
view.close();
}
};
var openView = function(view) {
view.render();
if (view.onShow) {
view.onShow();
}
};
rm.show = function(view) {
closeView(currView);
currView = view;
openView(currView);
};
return rm;
})();
这是我的 View 清理功能:
Backbone.View.prototype.close = function() {
if (this.onClose) {
this.onClose();
}
if (this.views) {
_.invoke(this.views, 'close');
}
// Unbind any view's events.
this.off();
// Unbind any model and collection events that the view is bound to.
if (this.model) {
this.model.off(null, null, this);
}
if (this.collection) {
this.collection.off(null, null, this);
}
// Clean up the HTML.
this.$el.empty();
};
我尝试将 View el
直接附加到 body
并在 View 清理函数中使用 this.remove();
(而不是使用常见的 el: $('#content')
向其附加元素,然后通过 this.$el.empty()
进行清理),但这也不起作用。
这可能与我的“全局事件”有关:
Backbone.Events.on('letterMouseDown', this.letterMouseDown, this);
但我用 onClose 函数来处理它们:
onClose: function() {
Backbone.Events.off('letterMouseDown');
}
最佳答案
我发现的一个问题是,您的 close
函数永远不会从 View 的 el
中删除事件委托(delegate)者。 View 的事件是通过使用 jQuery 的 on
的委托(delegate)者形式来处理的。将单个事件处理程序附加到 View 的 el
。您的 close
会:
this.$el.empty();
但这只会删除内容和附加到该内容的任何事件处理程序,它对直接附加到 this.el
的处理程序没有任何作用。考虑这个最小的例子:
var V = Backbone.View.extend({
events: {
'click': 'clicked'
},
clicked: function() {
console.log('still here');
}
});
var v = new V({ el: '#el' });
v.close();
之后,单击#el
将会在控制台中抛出'still here'
,即使您认为 View 已完全清理。演示:http://jsfiddle.net/ambiguous/aqdq7pwm/
添加 undelegateEvents
调用 close
应该可以解决这个问题。
一般建议:
不要使用老式的
on
和off
事件函数,使用listenTo
和stopListening
反而。listenTo
跟踪监听器上的事件,以便以后更轻松地将它们全部删除。将您的
close
简化为:Backbone.View.prototype.close = function() { if(this.onClose) this.onClose(); if(this.views) _.invoke(this.views, 'close'); this.remove(); };
不要将 View 绑定(bind)到现有的
el
。让 View 创建(并拥有)自己的el
并让调用者将该el
放入通常的容器中:var v = new View(); container.append(v.render().el);
模式。如果您必须附加到现有的
el
,那么 View 应该使用标准实现的稍微修改版本覆盖remove
:remove: function() { this.$el.empty(); // Instead of removing the element. this.undelegateEvents(); // Manually detach the event delegator. this.stopListening(); return this; }
关于javascript - 不可能的 Backbone 僵尸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33200663/