Angular JS ng-repeat 消耗更多浏览器内存

Posted

技术标签:

【中文标题】Angular JS ng-repeat 消耗更多浏览器内存【英文标题】:Angular JS ng-repeat consumes more browser memory 【发布时间】:2012-12-13 10:56:03 【问题描述】:

我有以下代码

<table>
 <thead><td>Id</td><td>Name</td><td>Ratings</td></thead>
 <tbody>
   <tr ng-repeat="user in users">
    <td>user.id</td>
    <td>user.name</td>
    <td><div ng-repeat="item in items">item.rating</div></td>
   </tr>
 </tbody>
</table>

users 是一个只有 id 和 name 的用户对象数组。数组中的用户对象数 - 150

items 是一个只有 id 和 rating 的 item 对象数组。数组中的项目对象数 - 150

当我在浏览器中渲染它时,当我尝试在我的 chrome - v23.0.1271.95 中进行分析时,它需要大约 250MB 的堆内存。

我正在使用 AngularJS v1.0.3。

角度有问题还是我在这里做错了什么?

这是 JS 小提琴

http://jsfiddle.net/JSWorld/WqSGR/5/

【问题讨论】:

【参考方案1】:

我想说泄漏在第二个数组中,因为您可能会遍历同一个数组并显示 users 中每个用户行的每个项目,因此取决于您的测试数据有多大,该视图可能会变得相当大。我可以做更多的调查。顺便说一句,你的小提琴完全不同。

【讨论】:

我已经更新了小提琴。不好意思,发错链接了。就我而言,问题仍然存在。为什么循环会消耗这么多内存。使用嵌套的 ng-repeats 通常有问题吗?【参考方案2】:

这不是 ng-repeat 本身。我认为这是您使用 item.rating 添加绑定的事实。

所有这些绑定都在作用域上注册手表,所以:

150 * 2 = 300(对于 2 个用户信息) 150 * 150 = 22500(用于评级信息) 总共 22800 个手表函数 + 22800 个 dom 元素。

这会将内存推到可以想象的 250MB 的值

来自Databinding in angularjs

你不能真正向用户展示超过 2000 条信息 人类在一个页面上。除此之外的任何东西都是非常糟糕的用户界面,并且 人类无论如何也无法处理这个。

【讨论】:

感谢 Liviu!我尝试为内部 ng-repeat 编写自定义指令。这实际上使内存减少了很多(大约 40MB )。这是相同的 JS Fiddle:jsfiddle.net/JSWorld/WqSGR/9 您要实现的实际用例是什么? 对于每个用户,我想按评分的降序列出他对每个可用项目的评分。 我很感兴趣为什么该指令会破坏内存使用量。为什么比ng-repeat效率高这么多?事实是您可能不应该一次显示这么多项目,但主体仍然存在。为什么不总是使用这样的指令?有人吗? @dg988 - 据我了解,指令版本中没有数据绑定。它只是将rating 的值直接替换为(在链接时)myItem.rating【参考方案3】:

现在您正在循环 150 X 150 = 22500 个项目。并为每个手表注册(或通过指令添加项目评级)。

相反 - 考虑将用户的评分添加到用户对象本身。它会增加每个用户对象的大小,但您只会循环 150 个项目并仅在它们上注册手表。

另外 - 考虑调查Indexes。很明显,可能存在相似的用户或项目评级。只需对它们进行索引,因此您可以减少它们,而不是循环遍历重物。

还有一件事——如果你要在同一个实例中运行指令,至少要更改代码:

var text = myTemplate.replace("rating",myItem.rating);

到一个concat样式的字符串计算:

var text = '<div>' + myItem.rating + '</div>';

这将为您节省一个 HUGE 块的计算。我为这种情况创建了一个JSperf,注意区别,它快了大约 99% ;-)

【讨论】:

以上是关于Angular JS ng-repeat 消耗更多浏览器内存的主要内容,如果未能解决你的问题,请参考以下文章

Angular.js ng-repeat 跨多个元素

angular.js > 如何在视图中获取内部 JSON 数据(使用 ng-repeat 指令)

Angular.js - ng-repeat 不显示更新的数组

angular.js ng-repeat 用于创建网格

Angular.js ng-repeat 跨越多个 tr

ng-repeat中的Angular js条件类