1

我正在开发一个单页应用程序,它使用 jqWidgets 库中的许多小部件(主要是网格和选项卡),这些小部件都是在页面加载时加载的。它变得相当大,我在使用后开始注意到(我强调使用,因为它不会在打开任何时间后开始滞后,但具体来说,在我的页面上打开和关闭一堆选项卡之后,每个选项卡都包含通过 Ajax 加载的多个网格,这些网格具有多个事件侦听器绑定到每个)网站几分钟后,用户界面变得非常缓慢,有时甚至没有响应,当页面刷新时,一切都再次顺利运行了几分钟,然后又回到了滞后状态。我仍在本地主机上进行测试。我最初的反应是 DOM 有太多元素(每个网格创建数百个 div!而且我有很多)所以与 ID 绑定的事件侦听器必须搜索太多元素并变得缓慢。如果是这种情况,它不会太难解决,是我的假设可能是罪魁祸首还是我有更糟糕的事情要担心?

更新:这里是内存时间线和堆快照的捕获。在内存时间线上没有与网站的交互,两个大的增加是页面刷新,中间的锯齿部分只是让我的网站闲置。

在此处输入图像描述

在此处输入图像描述

4

3 回答 3

2

听起来您确实在某处发生了内存泄漏。您是否使用了未正确控制的递归,或者您是否有可能提前结束的循环,但是当您在循环自然结束之前找到您正在寻找的东西时,您无法摆脱它们。你在使用这样的东西:

document.getElementById(POS.CurrentTableName + '-Menus').getElementsByTagName('td');

返回的节点列表很大,而您最终只使用了其中的一小部分。那些电话很昂贵。

它也可能是您选择的架构。每个网格数百个 div 在逻辑上听上去不是人脑可以管理的。您是通过 id 专门处理每个 div 还是它们只是您正在使用的 lib 的工件并且正在弄乱 DOM?你有没有在使用 DOM 时检查过它本身,看看你是否错误地在腹地添加了元素,并用你不使用的垃圾把 DOM 弄得乱七八糟,导致 DOM 在你使用应用程序时不断增长。您是否将事件处理程序添加到元素多次而不是一次?

作为比较,我也有一个单页应用程序(Google-Chrome 应用程序 - 多币种餐厅销售点),其中有 1,500 到 20,000 个事件处理程序注册调用 node.js 服务器上的 sqlite 后端。我主要使用纯 JS,除了 50 行 HTML 之外,其他所有代码都是用 JS 编写的。我将所有事件处理程序直接绑定到负责事件的最低级别元素。一些元素有多个处理程序(单击、更改、keydown、模糊等)。

该应用程序以眨眼速度运行,并且无论启动多长时间都保持如此快速。DOM 相当大,我会定期销毁并重新创建其中的很大一部分(清理并重新创建餐桌以供下次用餐),包括为每张餐桌添加多达 1,500 个事件处理程序。按下 CLEAR 按钮并用新表刷新屏幕几乎是不可察觉的,诚然在高端处理器上。我的开发环境是 Fedora 19 Linux。

于 2013-09-20T02:30:32.630 回答
2

没有看到任何代码示例,听起来还不错。

如果您有很多 jQuery 选择器,请尝试使它们尽可能具体。特别是如果您经常选择很多项目。

例如,如果您有一堆“abc”类,请尝试在此之前指定查看位置 - 例如,它们是否仅在表格单元格中找到?它们只在段落标签中找到吗?您使选择器越具体越好,就像您像这样指定选择器一样:

$('.class')

然后它将在整个 DOM 中搜索任何匹配的内容.class,但是,如果您按如下方式指定它:$('p .class')那么它将仅搜索该类的所有段落标签。

其他性能杀手正在连接事件,然后永远不会删除它们。如果您有任何代码删除附加了事件处理程序的元素,那么最佳做法是在删除元素时删除事件处理程序。否则,您将开始堆积孤立事件。

如果您正在执行大型单页应用程序,请查看诸如骨干 ( http://backbonejs.org/ ) 或 angular ( http://angularjs.org/ ) 之类的库,看看这是否可以帮助您 - 它们减轻了很多这些使用纯 jQuery 的人会遇到的问题。

最后,这篇文章(http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/)非常擅长概述您可以编写快速、高效的 javascript 以及如何避免常见的性能缺陷。

希望这可以帮助。

于 2013-09-20T01:42:06.927 回答
1

如果无法看到您的代码,准确地说有点困难。

如果 UI 在开始变得迟缓之前需要一点时间,那么听起来您的 JavaScript 中某处可能存在内存泄漏。当使用大量闭包以及嵌套函数和变量引用时,这种情况很快就会发生,而在你完成它们后没有清理它们。

此外,事件绑定到许多元素可能会大量消耗浏览器资源。如果可能,尝试使用事件委托来减少监听事件的元素数量。例如:$('table').on('click','td', myEventHandler);

小心确保事件绑定只发生一次,以避免无意中多次触发操作。

祝你好运!

于 2013-09-20T01:50:16.983 回答