ng-repeat和指令的角度性能问题

时间:2015-03-16 16:53:10

标签: javascript html angularjs performance

我目前正在处理一个有500行的表。每行有5个单元格。每个单元格都是一个指令。渲染此表大约需要3秒钟,它会锁定浏览器。

Timeline

99%的时间用在"解析HTML"我假设解析HTML指令的函数。 (当我向下滚动时,有许多Parse HTML函数。我猜测它的大约2500,无法找到计算它的方法。)

一个plnkr链接,您可以使用chrome dev工具查看问题(大部分时间都在解析HTML中):http://plnkr.co/edit/UouSapMYGgCNy7jEhlR6?p=preview

如果不手动连接每行的HTML字符串,我将如何进行优化呢?

       // Code goes here
  angular
    .module('app', [])
    .directive('cellOne', function() {
      return {
        scope: {
          data: '='
        },
        templateUrl: 'cell.html'
      };
    })
    .directive('cellTwo', function() {
      return {
        scope: {
          data: '='
        },
        templateUrl: 'cell2.html'
      };
    })
    .directive('row', function($compile) {
      return {
        compile: function compile() {
          return {
            pre: function preLink(scope, element) {

              var html = '';
              html += '<cell-one data=row[0]></cell-one>'
              html += '<cell-two data=row[1]></cell-two>'
              html += '<cell-one data=row[2]></cell-one>'
              html += '<cell-two data=row[3]></cell-two>'
              html += '<cell-two data=row[4]></cell-two>'
              var el = angular.element(html);
              var linkFunction = $compile(el);

              element.append(el);
              linkFunction(scope);
            }
          }
        }
      }
    })
    .controller('controller', function($scope) {
      $scope.data = [];
      // Fill the data map with random data
      $scope.refresh = function() {
        for (var i = 0; i < 500; ++i) {
          $scope.data[i] = {};
          for (var j = 0; j < 5; ++j) {
            $scope.data[i][j] = Math.random();
          }
        }
      }
      $scope.refresh()
    });

2 个答案:

答案 0 :(得分:1)

一个众所周知的事实是,当你有超过2000个观察者(负责处理你的数据绑定)时,Angular会出现性能问题。在你的情况下,你至少有2500。

减少数据绑定的数量肯定会有所帮助。 Angular最近引入了一次性数据绑定,如果绑定的数据不是完全动态的,您可以利用它。

我建议您查看Speeding up AngularJS apps with simple optimizations以获取更多信息。

答案 1 :(得分:1)

正如贾斯汀所提到的,减少手表有助于和$编译是非常昂贵的。当我看到这段代码时,有两件具体事情会跳出来:

1)使用&#39; =&#39;。这是双向绑定,但如果cellOne和cellTwo指令不会更改行,则会为每个单元格创建不必要的监视。 (请注意,即使在模板中进行插值时使用:: data语法,也会设置这些手表)。改为&#39;&amp;&#39;是一个快速的胜利。

2)每行都运行$ compile。 $ compile(和$ parse)相对昂贵。不知道你为什么不用模板参数来做这件事,但如果由于某种原因你需要使用$ compile,只需调用一次并缓存链接函数,而不是在指令的每个实例中调用$ compile。链接 - &gt;快..... $ compile - &gt;慢(相对)。在这两个优化中,这一个应该产生最大的影响。

Here is a plunk with these optimizations applied用于比较目的。

 angular
    .module('app', [])
    .directive('cellOne', function() {
      return {
        scope: {
          data: '&'
        },
        templateUrl: 'cell.html'
      };
    })
    .directive('cellTwo', function() {
      return {
        scope: {
          data: '&'
        },
        templateUrl: 'cell2.html'
      };
    })
    .directive('row', function() {
      return {
        template: '<cell-one data=row[0]></cell-one>' +
                  '<cell-two data=row[1]></cell-two>' +
                  '<cell-one data=row[2]></cell-one>' +
                  '<cell-two data=row[3]></cell-two>' +
                  '<cell-two data=row[4]></cell-two>'
      }
    })


<p>cell1: {{:: data() }}</p>