假设我已将各种事件侦听器附加到各种表单元素。后来,我想删除整个表单。
是否有必要(或建议)取消注册表单及其元素上存在的任何事件处理程序?如果是这样,删除元素集合上所有侦听器的最简单方法是什么?不这样做的后果是什么?如果重要的话,我正在使用Prototype。
这就是我实际在做的事情。我有一个简单的表格,如下:
<form id="form">
<input type="text" id="foo"/>
<input type="text" id="bar"/>
</form>
我在输入上观察了各种事件,例如:
$('foo').observe('keypress', onFooKeypress);
$('bar').observe('keypress', onBarKeypress);
等
表单通过AJAX提交,响应是表单的新副本。我将旧表单替换为新表单的副本$('form').replace(newForm)
。我是否积累了一大堆事件?
答案 0 :(得分:4)
未注销的事件可能无法自动释放内存。在旧版本的IE中,这尤其是一个问题。
Prototype曾经有一个自动垃圾收集系统,但该方法已在1.6版本中删除。记录here。是否删除该方法意味着不再进行垃圾收集,或者该方法不再公开,我不知道。另请注意,它只在页面卸载时被调用,这意味着如果您的用户在执行大量AJAX和DOM更新时长时间停留在同一页面上,即使在一次访问页面期间,内存也可能会泄漏到不可接受的程度。
答案 1 :(得分:3)
是的,有点。不足以成为一个巨大的问题,但在这种情况下,IE的旧版本会泄漏。
从Prototype 1.6.1开始(目前在其最终版本候选版本中),库在页面卸载时处理此清理。当您使用Prototype添加事件观察器时,它会在数组中保留对该元素的引用;在页面卸载时,它遍历该数组并删除所有观察者。
但是,如果用户要在此页面上停留一段时间,则内存使用量将在页面的整个生命周期中累积。您有几种选择:
在表单的祖先上侦听事件,永远不会被替换。然后,在您的处理程序中,检查事件的来源。 (即“事件授权”)
在致电Element#replace
之前,明确取消注册所有来电。在您的示例中,您将执行以下操作:
$('foo', 'bar').each(Element.stopObserving);
这相当于不带参数调用stopObserving
,这样可以删除给定元素上的所有处理程序。
我建议选项1。
(我们已经讨论过在Element#update
和Element#replace
的一部分中将Prototype的未来版本中的自动侦听器删除,但这是性能权衡。)
答案 2 :(得分:0)
如果Jonas在下面提到的场景中,从DOM中删除的元素中删除任何事件侦听器总是好的。