Suppose I have attached a variety of event listeners to various form elements. Later, I want to remove the entire form.
假设我已经将各种事件监听器附加到各种表单元素。后来,我想删除整个表单。
Is it necessary (or suggested) to unregister any event handlers that exist on the form and its elements? If so, what is the easiest way to remove all listeners on a collection of elements? What are the repercussions of not doing so? I'm using Prototype, if it matters.
是否有必要(或建议)取消注册表单及其元素上存在的任何事件处理程序?如果是这样,删除元素集合上所有侦听器的最简单方法是什么?不这样做的后果是什么?如果重要的话,我正在使用Prototype。
Here's what I'm actually doing. I have a simple form, like this:
这就是我实际在做的事情。我有一个简单的形式,像这样:
<form id="form">
<input type="text" id="foo"/>
<input type="text" id="bar"/>
</form>
I observe various events on the inputs, e.g.:
我在输入上观察了各种事件,例如:
$('foo').observe('keypress', onFooKeypress);
$('bar').observe('keypress', onBarKeypress);
etc.
The form is submitted via AJAX and the response is a new copy of the form. I replace the old form with a copy of the new one doing something like $('form').replace(newForm)
. Am I accumulating a bunch of event cruft?
表单通过AJAX提交,响应是表单的新副本。我将旧表单替换为新表单的副本,例如$('form')。replace(newForm)。我在积累一堆活动吗?
3 个解决方案
#1
Yeah, a bit. Not enough to be a huge problem, but older versions of IE will leak under those circumstances.
是的,有点。这不足以成为一个巨大的问题,但在这种情况下,IE的旧版本会泄漏。
As of Prototype 1.6.1 (currently in its final release candidate), the library handles this cleanup on page unload. When you use Prototype to add an event observer, it keeps a reference to that element in an array; on page unload, it loops through that array and removes all your observers.
从Prototype 1.6.1开始(目前在其最终版本候选版本中),库在页面卸载时处理此清理。当您使用Prototype添加事件观察器时,它会在数组中保留对该元素的引用;在页面卸载时,它循环遍历该数组并删除所有观察者。
However, if the user is going to stay on this page for a while, memory usage will accumulate over the life of the page. You have several options:
但是,如果用户要在此页面上停留一段时间,则内存使用量将在页面的整个生命周期中累积。你有几个选择:
-
Listen for events on an ancestor of the form, one that never gets replaced. Then, in your handler, check where the event came from. (i.e., "event delegation")
聆听表格祖先的事件,永远不会被取代。然后,在您的处理程序中,检查事件的来源。 (即“事件授权”)
-
Explicitly un-register all your calls before calling
Element#replace
. In your example, you'd do:在调用Element#replace之前,显式取消注册所有调用。在您的示例中,您将执行以下操作:
$('foo', 'bar').each(Element.stopObserving);
This is equivalent to calling stopObserving
with no arguments, which has the effect of removing all handlers on a given element.
这相当于调用不带参数的stopObserving,这样可以删除给定元素上的所有处理程序。
I would recommend option 1.
我会建议选项1。
(We've talked about doing automatic listener removal in a future version of Prototype as part of Element#update
and Element#replace
, but it's a performance trade-off.)
(我们已经讨论过在未来版本的Prototype中删除自动侦听器作为Element#update和Element#replace的一部分,但这是性能权衡。)
#2
Events which are not unregistered may not free their memory automatically. This is especially a problem in older versions of IE.
未注销的事件可能无法自动释放内存。在旧版本的IE中,这尤其是个问题。
Prototype used to have an automatic garbage collection system for this, but the method has been removed in version 1.6. It is documented here. Whether the removal of the method means that the garbage collection no longer takes place, or the method just isn't publicly available anymore, I don't know. Also note that it was only ever called on page unload, meaning that if your users stay on the same page for a long time while doing a lot of AJAX and DOM updates, memory may leak to an unacceptable extent even during that one page visit.
原型曾经有一个自动垃圾收集系统,但该方法已在1.6版本中删除。这里记录在案。是否删除该方法意味着不再进行垃圾收集,或者该方法不再公开,我不知道。另请注意,它只在页面卸载时被调用,这意味着如果您的用户在执行大量AJAX和DOM更新时长时间停留在同一页面上,即使在一次访问页面期间,内存也可能会泄漏到不可接受的程度。
#3
It's always good to remove any event listeners from elements that are removed from the DOM in case of the scenario that Jonas mentioned below.
如果Jonas在下面提到的场景中,从DOM中删除的元素中删除任何事件侦听器总是很好的。
#1
Yeah, a bit. Not enough to be a huge problem, but older versions of IE will leak under those circumstances.
是的,有点。这不足以成为一个巨大的问题,但在这种情况下,IE的旧版本会泄漏。
As of Prototype 1.6.1 (currently in its final release candidate), the library handles this cleanup on page unload. When you use Prototype to add an event observer, it keeps a reference to that element in an array; on page unload, it loops through that array and removes all your observers.
从Prototype 1.6.1开始(目前在其最终版本候选版本中),库在页面卸载时处理此清理。当您使用Prototype添加事件观察器时,它会在数组中保留对该元素的引用;在页面卸载时,它循环遍历该数组并删除所有观察者。
However, if the user is going to stay on this page for a while, memory usage will accumulate over the life of the page. You have several options:
但是,如果用户要在此页面上停留一段时间,则内存使用量将在页面的整个生命周期中累积。你有几个选择:
-
Listen for events on an ancestor of the form, one that never gets replaced. Then, in your handler, check where the event came from. (i.e., "event delegation")
聆听表格祖先的事件,永远不会被取代。然后,在您的处理程序中,检查事件的来源。 (即“事件授权”)
-
Explicitly un-register all your calls before calling
Element#replace
. In your example, you'd do:在调用Element#replace之前,显式取消注册所有调用。在您的示例中,您将执行以下操作:
$('foo', 'bar').each(Element.stopObserving);
This is equivalent to calling stopObserving
with no arguments, which has the effect of removing all handlers on a given element.
这相当于调用不带参数的stopObserving,这样可以删除给定元素上的所有处理程序。
I would recommend option 1.
我会建议选项1。
(We've talked about doing automatic listener removal in a future version of Prototype as part of Element#update
and Element#replace
, but it's a performance trade-off.)
(我们已经讨论过在未来版本的Prototype中删除自动侦听器作为Element#update和Element#replace的一部分,但这是性能权衡。)
#2
Events which are not unregistered may not free their memory automatically. This is especially a problem in older versions of IE.
未注销的事件可能无法自动释放内存。在旧版本的IE中,这尤其是个问题。
Prototype used to have an automatic garbage collection system for this, but the method has been removed in version 1.6. It is documented here. Whether the removal of the method means that the garbage collection no longer takes place, or the method just isn't publicly available anymore, I don't know. Also note that it was only ever called on page unload, meaning that if your users stay on the same page for a long time while doing a lot of AJAX and DOM updates, memory may leak to an unacceptable extent even during that one page visit.
原型曾经有一个自动垃圾收集系统,但该方法已在1.6版本中删除。这里记录在案。是否删除该方法意味着不再进行垃圾收集,或者该方法不再公开,我不知道。另请注意,它只在页面卸载时被调用,这意味着如果您的用户在执行大量AJAX和DOM更新时长时间停留在同一页面上,即使在一次访问页面期间,内存也可能会泄漏到不可接受的程度。
#3
It's always good to remove any event listeners from elements that are removed from the DOM in case of the scenario that Jonas mentioned below.
如果Jonas在下面提到的场景中,从DOM中删除的元素中删除任何事件侦听器总是很好的。