【发布时间】:2015-07-10 03:40:37
【问题描述】:
我正在使用 AngularJS 渲染日历 UI,并且在周转数周时遇到了一些相当大的性能问题。让我解释一下。
用户界面看起来像这样:
我循环遍历所有的人,然后为每个人循环遍历这些天,然后为该用户呈现当天的日历对象。像这样(简化):
<div ng-repeat="user in ::ctrl.users track by user.id" class="row">
<div ng-repeat="day in ctrl.days" class="cell">
<div ng-repeat="item in ctrl.items[user.id][day] track by item.id">
<div class="item">
此页面上的观察者数量并不多(大约 500 个),几乎所有内容都绑定一次。
问题是当用户单击上一个/下一个按钮来加载上一周或下一周时。这会用新的日期更改 ctrl.days 数组,并加载所有正确的项目。在您拥有大量人员和日历项目之前,这可以正常运行。那么所有 DOM 元素的销毁和重新创建真的很慢。
我遇到了 sly-repeat 指令,该指令旨在缓存和重用 DOM 元素,但由于我的外部 ng-repeat 更改(ctrl.days),内部 ng-repeat(带有项目)也被重新创建。所以它并没有真正起作用。
我该如何解决这个问题?现在浏览大型数据集需要大约 2 秒的时间,这当然是不可接受的。只需一小部分用户和日历项目,一切都非常活泼。
【问题讨论】:
-
为所有天(即所有周)生成 DOM,并让前一周和下周按钮更改索引。然后,您可以使用此索引来更改日期的可见性(或其他一些 CSS 类)。希望这是有道理的。
-
日历基本上是无限的,并不是预先生成所有这些项目的选项。即使我将它限制为 4 周,它仍然是成千上万的 DOM 元素......
-
如果您的视口大小将被固定。您可以预先创建 DOM 并单独换出值。{{x}}{{y}}{{z}}之类的东西,您只需更改 x、y、z 而不是循环通过具有 x、y 和 z 的集合并创建 div。如果我理解正确,您的开销是由于 DOM 创建/重新创建 - 所以这应该会有所帮助(但会增加复杂性)
-
在尝试/发明了很多相同问题的解决方案之后......,我的结论是在指令中使用 react.js。当数据更新必须手动时,**controller => directive **。类似
$scope.watch('data' ,function(newval) { myReactDirective.update(newval) });这是一个防弹解决方案 -
您也可以摆脱其中一个 ng-repeats,因为页面上的天数可能不会改变。
标签: angularjs performance dom angularjs-ng-repeat