Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 单页应用程序-大DOM-速度慢_Javascript_Html_Performance_Dom - Fatal编程技术网

Javascript 单页应用程序-大DOM-速度慢

Javascript 单页应用程序-大DOM-速度慢,javascript,html,performance,dom,Javascript,Html,Performance,Dom,我正在开发一个单页应用程序,它使用了很多小部件,主要是jqWidgets库中的网格和选项卡,这些小部件都是在页面加载时加载的。它变得越来越大,我开始注意到在使用后我强调使用,因为它在打开任何时间后都不会开始滞后,但具体来说,在打开和关闭我页面上的一系列选项卡之后,每个选项卡都包含通过Ajax加载的多个网格,这些网格有多个事件监听器连接到每个站点上几分钟。UI变得非常缓慢,有时没有响应,当页面刷新时,所有内容都会在几分钟内再次顺畅运行,然后返回laggy。我还在本地主机上测试。我最初的反应是DOM

我正在开发一个单页应用程序,它使用了很多小部件,主要是jqWidgets库中的网格和选项卡,这些小部件都是在页面加载时加载的。它变得越来越大,我开始注意到在使用后我强调使用,因为它在打开任何时间后都不会开始滞后,但具体来说,在打开和关闭我页面上的一系列选项卡之后,每个选项卡都包含通过Ajax加载的多个网格,这些网格有多个事件监听器连接到每个站点上几分钟。UI变得非常缓慢,有时没有响应,当页面刷新时,所有内容都会在几分钟内再次顺畅运行,然后返回laggy。我还在本地主机上测试。我最初的反应是DOM有太多的元素,每个网格创建数百个div!我有很多,所以绑定到ID的事件侦听器必须搜索太多的元素,而且速度会变慢。如果是这样的话,修复起来就不太难了,我的假设可能是罪魁祸首还是我有更糟糕的事情要担心

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


没有看到任何代码示例,这听起来并不太糟糕

如果您有很多jQuery选择器,请尝试使这些选择器尽可能具体。尤其是当你在很多时候选择了很多东西的时候

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

document.getElementById(POS.CurrentTableName + '-Menus').getElementsByTagName('td');
$“.class”

然后它将在整个DOM中搜索与.class匹配的任何内容,但是,如果您按如下方式指定它:$'p.class',则它将只搜索该类的所有段落标记

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

如果您正在开发一个大型的单页应用程序,请查看诸如主干或angular之类的库,看看这是否可以帮助您—它们可以缓解许多使用普通jQuery的人将遇到的问题

最后,这篇文章非常擅长概述如何编写快速、高效的javascript,以及如何避免常见的性能陷阱


希望这有帮助。

在没有看到任何代码示例的情况下,它听起来并不太糟糕

如果您有很多jQuery选择器,请尝试使这些选择器尽可能具体。尤其是当你在很多时候选择了很多东西的时候

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

document.getElementById(POS.CurrentTableName + '-Menus').getElementsByTagName('td');
$“.class”

然后它将在整个DOM中搜索与.class匹配的任何内容,但是,如果您按如下方式指定它:$'p.class',则它将只搜索该类的所有段落标记

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

如果您正在开发一个大型的单页应用程序,请查看诸如主干或angular之类的库,看看这是否可以帮助您—它们可以缓解许多使用普通jQuery的人将遇到的问题

最后,这篇文章非常擅长概述如何编写快速、高效的javascript,以及如何避免常见的性能陷阱


希望这有帮助。

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

如果UI在开始变慢之前花了一点时间,那么听起来可能是JavaScript中的某个地方出现了内存泄漏。当使用大量闭包以及嵌套函数和变量引用时,这种情况会很快发生,而在使用完它们后,不会清理它们

此外,与许多元素的事件绑定可能会极大地消耗浏览器资源。如果可能,尝试使用事件委派来减少侦听事件的元素数量。例如: $‘表’。点击‘点击’、‘td’,myEventHandler

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


祝你好运

如果看不到您的代码,那么准确地说有点困难

如果UI需要一点时间 在它开始变迟钝之前,有一点是错误的,然后听起来可能是JavaScript中的某个地方出现了内存泄漏。当使用大量闭包以及嵌套函数和变量引用时,这种情况会很快发生,而在使用完它们后,不会清理它们

此外,与许多元素的事件绑定可能会极大地消耗浏览器资源。如果可能,尝试使用事件委派来减少侦听事件的元素数量。例如: $‘表’。点击‘点击’、‘td’,myEventHandler

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


祝你好运

听起来确实有内存泄漏。您使用的是没有得到适当控制的递归,还是有可以提前结束的循环,但当您在循环自然结束之前找到要查找的内容时,却无法突破它们。您使用的是这样的东西吗:

document.getElementById(POS.CurrentTableName + '-Menus').getElementsByTagName('td');
其中nodelist返回的值很大,而您最终只使用了其中的一小部分。那些电话很贵

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

作为比较,我也有一个单页的应用程序Google Chrome应用程序-多货币餐厅销售点,其中注册了1500到20000个事件处理程序,在node.js服务器上调用sqlite后端。我使用的大多是纯JS,除了50行之外,所有HTML都是用JS编写的。我将所有事件处理程序直接绑定到负责事件的最低级别元素。有些元素有多个处理程序,如单击、更改、向下键、模糊等


该应用程序以眨眼速度运行,并且无论运行多长时间都保持如此快速。DOM相当大,我经常破坏并重新创建其中的大部分。餐厅的桌子会被清理并重新创建,以备下次使用,包括每个桌子添加多达1500个事件处理程序。在高端处理器上,点击CLEAR(清除)按钮,屏幕上就会出现新的表格,这几乎是不可察觉的。我的开发环境是Fedora19Linux。

听起来确实有内存泄漏。您使用的是没有得到适当控制的递归,还是有可以提前结束的循环,但当您在循环自然结束之前找到要查找的内容时,却无法突破它们。您使用的是这样的东西吗:

document.getElementById(POS.CurrentTableName + '-Menus').getElementsByTagName('td');
其中nodelist返回的值很大,而您最终只使用了其中的一小部分。那些电话很贵

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

作为比较,我也有一个单页的应用程序Google Chrome应用程序-多货币餐厅销售点,其中注册了1500到20000个事件处理程序,在node.js服务器上调用sqlite后端。我使用的大多是纯JS,除了50行之外,所有HTML都是用JS编写的。我将所有事件处理程序直接绑定到负责事件的最低级别元素。有些元素有多个处理程序,如单击、更改、向下键、模糊等


该应用程序以眨眼速度运行,并且无论运行多长时间都保持如此快速。DOM相当大,我经常破坏并重新创建其中的大部分。餐厅的桌子会被清理并重新创建,以备下次使用,包括每个桌子添加多达1500个事件处理程序。在高端处理器上,点击CLEAR(清除)按钮,屏幕上就会出现新的表格,这几乎是不可察觉的。我的开发环境是Fedora19Linux。

Chrome中的内存时间线是怎么说的?如果它不断增长,你就会出现内存泄漏,这可能意味着很多死掉的事件处理程序等仍然挂在内存中。@MattGreer感谢你给我指出内存时间线,我总是打开chrome开发工具,但我不知道这个功能,我是个新手。所以时间线显示记忆在增长,然后一次又一次地下降,这个图形几乎代表了类似锯片的形状。我不知道
由于所有的小部件,DOM数量相当高,这是我所期望的,但它并没有失控。失控的是事件侦听器计数,当打开/关闭选项卡时,计数开始快速增长!从7000开始,很快到11000+Chrome中的内存时间线是怎么说的?如果它不断增长,你就会出现内存泄漏,这可能意味着很多死掉的事件处理程序等仍然挂在内存中。@MattGreer感谢你给我指出内存时间线,我总是打开chrome开发工具,但我不知道这个功能,我是个新手。所以时间线显示记忆在增长,然后一次又一次地下降,这个图形几乎代表了类似锯片的形状。我不认为DOM数量是相当高的40000,这是我所期望的,因为所有的小部件,但它并没有失控。失控的是事件侦听器计数,当打开/关闭选项卡时,计数开始快速增长!从大约7000开始,很快到11000+疯狂的div数量是widget库的副产品,我已经验证了当网格被移除,或者包含网格的选项卡被关闭时,元素从DOM中移除。我还需要清理空的/旧的事件监听器我认为这是一个很大的贡献,因为我的页面在打开和关闭一堆包含多个网格的选项卡后变得滞后,多个事件监听器绑定到每个选项卡上,而不仅仅是打开一段时间,但是在使用了一段时间之后……我设置了我的*.js文件,其中一个处理创建内容,另一个处理创建后的操作,另一个处理实用程序方面。通过分离功能,我将应用程序分解为易于调试的可管理块。添加处理程序仅由创建代码控制,并且不可能对每个元素运行多次。开始为每个事件处理程序创建添加console.log stmts,以查看是否在创建端加倍。在每个处理程序中添加更多的控制台stmt,以查看在使用应用程序时事件触发是否有意义。好的,我重新编写了代码,以便在关闭选项卡时销毁所有小部件,使用.off删除由.on创建的所有处理程序,并使用.empty清空包含的DIV。这就大大提高了性能。然而,仍然有一些事件监听器在150-200左右被添加,我似乎无法在我的代码中再次找到,可能是小部件库的副产品,有没有办法查看操作期间添加的所有事件监听器?我不知道有没有办法问系统某个特定元素上是否有事件监听器。事实上,我在添加事件处理程序的元素中添加了一个属性“data has handler”。根据元素的不同,我知道这个特定的属性意味着有1个、2个或更多的处理程序连接,并且在必要时我会将它们全部核化。这只是因为我绝对知道某个元素有一个特定的处理程序集合。虽然您的小部件库可能在某种意义上对您有利,但在另一种意义上也对您有害,因为它隐藏了您可能需要了解的内容。值得吗?大量的div是widget库的副产品,我已经验证了当网格被移除,或者包含网格的选项卡被关闭时,元素被从DOM中移除。我还需要清理空的/旧的事件监听器我认为这是一个很大的贡献,因为我的页面在打开和关闭一堆包含多个网格的选项卡后变得滞后,多个事件监听器绑定到每个选项卡上,而不仅仅是打开一段时间,但是在使用了一段时间之后……我设置了我的*.js文件,其中一个处理创建内容,另一个处理创建后的操作,另一个处理实用程序方面。通过分离功能,我将应用程序分解为易于调试的可管理块。添加处理程序仅由创建代码控制,并且不可能对每个元素运行多次。开始为每个事件处理程序创建添加console.log stmts,以查看是否在创建端加倍。在每个处理程序中添加更多的控制台stmt,以查看在使用应用程序时事件触发是否有意义。好的,我重新编写了代码,以便在关闭选项卡时销毁所有小部件,使用.off删除由.on创建的所有处理程序,并使用.empty清空包含的DIV。这就大大提高了性能。然而,仍然有一些事件监听器在150-200左右被添加,我似乎无法在我的代码中再次找到,可能是小部件库的副产品,有没有办法查看操作期间添加的所有事件监听器?我不知道有没有办法问系统某个特定元素上是否有事件监听器。事实上,我在添加事件处理程序的元素中添加了一个属性“data has handler”。取决于元素,我知道 这个特殊的属性意味着有1个、2个或更多的处理程序,我会在必要时将它们全部核化。这只是因为我绝对知道某个元素有一个特定的处理程序集合。虽然您的小部件库可能在某种意义上对您有利,但在另一种意义上也对您有害,因为它隐藏了您可能需要了解的内容。值得吗?