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 > 如何在视图中获取内部 JSON 数据(使用 ng-repeat 指令)