10

如何将内联 javascript 事件与其 HTML 元素完全解除绑定?

我试过了:

  • 从 body 元素取消对事件的委托
  • 解除事件与元素的绑定
  • 甚至从 HTML 元素中删除 event 属性

至少令我惊讶的是,只有删除onchange属性 ( .removeAttr('onchange')) 才能防止事件再次触发。

<input type="text" onchange="validateString(this)"></input>

我知道这对代表来说是可能的,这可能是最好的方法,但只是在这里玩。这个例子纯粹是为了提出问题而假设的。


所以假设的情况是这样的:

我正在编写一个 javascript 验证库,该库通过内联 HTML 属性将 javascript 事件绑定到输入字段,如下所示:

<input type="text" onchange="validateString(this)"></input>

但是,我想通过解除绑定我的事件来使库更好一点,这样在单页应用程序中使用这个库的人就不必管理我的事件处理程序,也不必混乱他们的代码通过将输入事件连接到我假设的验证库中的函数......无论如何。这些都不是真的,但它似乎是一个不错的用例。

这是假设验证 Library.js 的“示例”代码:

http://jsfiddle.net/CoryDanielson/jwTTf/


要进行测试,只需在文本框中输入,然后单击其他地方来触发更改事件。在“时间轴”选项卡上打开并记录 Web 检查器来执行此操作。突出显示与您触发 change 事件(多次触发 change 事件)相关的时间线区域,您将看到事件侦听器(在下面的窗口中)在每个 change 事件上增加 100。如果正确管理和删除,每个事件侦听器都会在呈现新输入之前被正确删除,但我还没有找到一种方法来使用内联 javascript 事件正确地做到这一点。

该代码的作用是:

  1. onChange,输入元素触发验证功能
  2. 该函数验证输入并在成功时为边框着色
  3. 然后在 1 秒后(为了演示内存泄漏),输入元素连续 100 次替换为相同的 HTML,而没有取消绑定更改事件(因为我不知道该怎么做……这就是问题所在)。这模拟了在单页应用程序中更改视图。这会在 DOM 中创建 100 个新的事件侦听器,这些事件侦听器可以通过 Web 检查器看到。

    • 有趣的笔记。$('input').removeAttr('onchange');实际上会阻止 onchange 事件在未来被触发,但不会垃圾收集 web 检查器中可见的 eventListener/DOM 内容。

此屏幕截图是在更改事件触发 3 次之后。每次,100 个新的 DOM 节点都使用相同的 HTML 呈现,我尝试onchange在替换 HTML 之前从每个节点取消绑定事件。

在此处输入图像描述


更新:我回到这个问题,只是使用 JSFiddle 做了一个快速的小测试,以确保答案是有效的。我运行了数十次“测试”,然后等待——果然,GC 通过并处理了事务。

在此处输入图像描述

4

2 回答 2

3

我不认为你有什么可担心的。尽管无法再引用内存并且最终会被垃圾回收,但它仍会显示在 Web Inspector 内存窗口中。当 GC 决定对内存进行垃圾收集时(例如,当浏览器内存不足或某个固定时间后),内存将被垃圾收集。细节取决于 GC 实现者。您可以通过单击 Web Insepctor 窗口底部的“收集垃圾”按钮来验证这一点。我正在运行 Chrome 23,并且在您的验证框中输入文本大约 5 或 6 次后,内存使用率下降,显然是由于垃圾收集。

这种现象并非特定于内联事件。我看到了类似的模式,只是通过重复分配一个大数组然后覆盖对该大数组的引用,为 GC 留下大量孤立内存。内存增加了一段时间,然后 GC 启动并完成其工作。

于 2013-02-09T07:36:38.723 回答
0

我的第一个建议是使用off('change'),但似乎你已经尝试过了。它不工作的原因可能是因为处理程序没有附加.on('change'). 我不太了解 jQuery 如何在内部处理这样的侦听器,但请尝试使用.on('change', function ()...or.bind('change', function ()...代替。

于 2013-02-09T07:21:03.387 回答