数据绑定对象的角度性能限制:我现在放弃AngularJS吗?

时间:2014-03-29 01:48:59

标签: performance angularjs architecture

在下面的讨论this article中,Renan Cakirerk评论说,根据Angular开发人员的说法,Angular UI性能可能会降低到2000个数据绑定对象之外。

这让我认真考虑用Angular追求我的非平凡应用程序是一个好主意。一个好的应用程序毕竟是一个快速的应用程序我不想花几个月的时间来建造一些最终会被咬的东西。

我有兴趣听取Angular 非平凡应用建设者关于

的信息
  • 人们成功用于处理性能下降的一般策略
  • 基于我的要求和设计模式的具体策略(下)
  • 我是否应该在项目的早期阶段完全放弃Angular,以避免迫在眉睫的“停滞不前”

等待可能的“ES6电源和性能如Object.observe”以及未来的版本可能会让开发人员对$apply / {{1}进行更细粒度的控制,这是一个太大的风险循环以便$digest - 可以触发有限的脏检查“(Brian Frichette在同一个讨论中提到了这些)。我想知道复杂的应用程序今天在v1.2.15上可以很快。

关于我的问题/解决方案的更多细节......

我正在构建一个具有非常丰富功能的应用程序,其中每个对象(例如用户)都可以执行许多功能,例如将它们链接到其他用户,更改其属性,向其发送消息等。

规范在此对象上有超过20个函数:可放置区域,上下文相关工具栏图标(例如,当您选择某些文本时,Word具有出现在鼠标附近的迷你工具栏的方式)。

这些选项需要根据某些鼠标操作进行隐藏和显示,例如悬停和拖动,并依赖于特定用户对象的状态(在某些情况下会显示许多图标和拖放选项,而不会显示其他用户)

现在,我开始构建此方法的方法是将每个单独的图标和拖放区域,拖动句柄等作为单独的数据绑定元素与ng-show(或类似)这是我们自定义业务逻辑的关键。

例如

$scope

假设上面的2000理论极限值得担心,那么20个自定义可显示的可隐藏位意味着100个用户(使用惊人的ng-repeat显示)是我的极限!也许显示100是愚蠢的,我可以通过过滤等攻击这个,但在我看来,除以20大大减少了我的对象“带宽”。当老板希望增加10个功能时会发生什么?

如果我以jQuery方式执行此操作,我可能会根据需要构建并销毁许多图标和菜单项。每个悬停/拖动的响应性稍差,但至少应用程序可以按比例缩放对象的数量。

4 个答案:

答案 0 :(得分:4)

我遇到了一些臭名昭着的重复性能问题。我有一个大约10列的表,每天包含一行。如果我尝试:

<tr ng-repeat="row in rows">
  <td ng-repeat="column in columns">
    {{ row[column.id] }}
  </td>
</tr>

在100-200天的订单创建后,我遇到了性能问题。

但事实是,这种方法有很多愚蠢的事情。首先,没有显示可以显示这么多行。为什么要在屏幕上添加一堆废话而不会被渲染?此外,正如其他人已经明白的那样,用户不太可能有意义地与页面上的足够项目进行交互以保证2k绑定。

我将使用一些复杂的预渲染行甚至整个表来编译所有的html,然后每次对表数据进行更改时都会更新。但后来我在行中想要绑定一些小部件。

相反,我去了 http://binarymuse.github.io/ngInfiniteScroll/ 它使您可以非常轻松地从页面中动态添加或删除项目。现在我可以随时显示40行,当用户向任一方向滚动时,它会附加新行并摆脱旧行。我不得不做一些修改来实现删除元素部分,但对我来说它是迄今为止最好的选择,因为它允许我坚持我真正喜欢的angularjs心态,并且仍然可以获得良好的性能。

在我看来,使用ng-if而不是ng-show可以相当简单地解决您的问题。如果从DOM中删除元素,则该项的绑定不应再存在问题。

如果有必要的话,应该很容易用你所拥有的和一些额外的ng重复测试吗?它非常容易插入无限滚动以使其旋转。

答案 1 :(得分:1)

您可能希望在应用任何优化之前先找到真正的瓶颈。您可以将Chrome DevTools与代码段一起使用来分析您的代码,请参阅http://bahmutov.calepin.co/improving-angular-web-app-performance-example.html

答案 2 :(得分:0)

我们也遇到性能问题,UI开始卡住,花了很多时间来处理数据绑定对象,经过一些测试后我们意识到 ngRepeat 会为每个元素添加$ watch并作为结果对绩效有直接影响。

我们认为最好的方法是自己使用DOM,我们创建了自己的 ngRepeat 指令,并使用本机JavaScript API(或JQuery,它并不重要)迭代元素),我们还使用CreateDocumentFragment进行DOM操作(why是否要使用 CreateDocumentFragment )。

示例:

  mainApp.directive("myRepeater", function () {
   var LIST_ITEM = "li";
        return {            
            restrict: "A",
            link: function (scope, element, attrs) {
                var rawElm = element[0];        
                scope.$watch(attrs.source, function(newValue) {
                    if (!newValue || !newValue.length || newValue.length === 0) return;

                    // wipe the previous list
                    rawElm.innerHTML = "";
                    var frag = document.createDocumentFragment();

                    newValue.forEach(function (item) {
                        var listItemNd = document.createElement(LIST_ITEM);
                        var textNd = document.createTextNode("your text");
                        listItemNd.appendChild(textNd);
                        frag.appendChild(listItemNd);
                    });

                    rawElm.appendChild(frag);
                });
            }
        };
    });

答案 3 :(得分:-1)

2014年的答案应该是:是的,现在放弃Angular。

与Urban_racoons所说的相反,在用户可以看到并有意义地与之交互的页面上容易拥有100-200个项目。

例如,7天显示屏上的Google日历在我的显示器上显示18小时的1/2小时块。如果每个人都有一个ng-class,那么你就有252块手表。但是,如果您想要所有Google日历功能,那么您需要ng-clicksng-if

另一方面,在我自己的应用程序中,只有一个标题,一些面板,一个左侧导航菜单(~5个项目)和详细信息窗格,其中有~5个标签和详细信息窗格中的~30个项目,我有&gt; 3000只手表(感谢ng-stats)。

不仅如此,仅渲染这30个项目需要2秒钟 - Chrome devtools“个人资料”标签显示所有controllersBoundTranscludenodeLinkFnngWatchIfAction s {{1}应该是救世主,但我每个项目都有一些,所以有时间评估这些并渲染结果加起来)。

问题是,如果我这样做,我会被诅咒(将ng-if放在任何地方意味着重新渲染时间显示ng-if隐藏的项目很慢,甚至ng-if是如果我不这样做,那该死的(把ng-infinite-scroll表示手表加起来不可接受的程度)。

所以我不得不求助于一堆黑客和优化,例如 在

在我看来,这些优化应该出现在Angular核心中。

2016年更难的问题,已经编写了1000行代码:我现在应该放弃AngularJS吗?