Angular 1.x vs 2更改检测性能

时间:2016-06-05 18:55:10

标签: angular angular2-changedetection

我一直在玩AngularJS 1.x和Angular 2,试图比较他们的表现。

这是Plunkr显示Angular 1.x的“下方”。如果作用域中存在太多元素,您将注意到在编辑输入字段时会出现滞后,因为每次检测到可能已更改的事件时,框架都会检查作用域上的所有元素。

摘自第一个Plunkr(html):

<body ng-app="myApp">
<div ng-controller="myCtrl">
  <input ng-model ="name"></input>
  Hello, {{name}}!
  <button ng-click="generateFields()">
    Generate 5000 elements
  </button>
  {{list}}
</div>

摘自第一个Plunkr(js):

myApp.controller('myCtrl', function($scope) {
$scope.name = 'name';
$scope.list = [];

$scope.generateFields = function(){
    for(i=0; i<5000;i++){
    $scope.list.push(i);
  }
}

});

在这个Plunkr中,我在Angular 2中写了一个类似的样本。似乎根本没有滞后。如何在Angular 2中解决这个问题?框架是否知道只有输入字段被更改,或者由于VM优化的变化检测器而在执行脏检查时更快?

摘自第二个Plunkr:

@Component({
 selector: 'my-app',
  providers: [],
  template: `
    <div>
      <div>{{myProp}}</div>
      <input [(ngModel)]="myProp" />
      <button (click)="generateFields()">Generate</button>
      <div>{{myList}}</div>
    </div>
  `,
  directives: []
})
export class App {
  constructor() {
  }

  myProp :string = "Change me!";
  myList :any = [];

  generateFields(){
     for (var i = 1; i < 5000; i++)
     {       
          this.myList.push(i);
     }

    console.log("fields generated");
  }
}

2 个答案:

答案 0 :(得分:4)

完全。 Angular2 CD非常高效,因为它在绑定和事件中使用区域和双向绑定的分割。您可以使用ChangeDetectionStrategy.OnPush进一步优化

  

因为更改检测在prodmode中只运行一次?我没有尝试过,因为我没有注意到角度2示例中的任何滞后,无论列表中添加了多少元素。

我不知道Angular 1.x,因此我无法说明为什么它会变慢。 Angular2仅在触发订阅事件或完成异步调用时运行更改检测。 Angular也没有比较对象或数组的内容,它只做===检查。

  

如果这是angular只做===检查的情况,那么在你点击第二个plunkr中的Generate按钮后,它怎么知道它需要将更改传播到DOM?元素将添加到数组中,但不会更改数组对象的引用。

我认为这是因为<div>{{myList}}</div>绑定到myList.toString()并且在每个更改检测周期(例如在按钮点击之后)它比较了包含不同值时不同的结果。例如,如果你改为<child-comp [data]="myList">,那么当ChildComponent没有绑定到{{myList}}时就不会发生任何事情。

答案 1 :(得分:1)

  

由于VM优化的变化检测器,它在执行脏检查方面是否更快?

很难说,因为Angular 2中的变化检测与Angular 1完全不同。我认为唯一相同的是脏检查模板绑定的(逻辑)概念。最有可能的是单态(VM友好/优化)代码 - Angular blogthoughtram blogV.Savkin talk - Angular 2在变换检测器中为每个组件创建的对象中生成。 / p>

  

请看看第二个plunkr,我刚刚更新了它。现在它有一个子组件,它将列表作为输入参数。一旦我介绍了它,由于默认的CD策略,Angular被迫对阵列进行深度检查,这意味着只要生成足够的元素,性能就会显着降低。尽管如此,它仍然比角度1快得多。底线,输入参数会在默认CD策略的情况下进行深度检查,但是组件“本地”和/或变量不是。

     

...由于Property绑定是另一个绑定表达式,它使Angular默认进行深度检查。

如果模板绑定包含可迭代的内容 - 例如[myList]="myList" - 然后仅在开发模式中,则更改检测实际上遍历所有(例如myList)项目并比较它们,即使没有NgFor循环或其他创建绑定到子组件中每个元素的模板的东西。这与在生产模式下执行的looseIdentical()检查(即===检查,因此参考检查)非常不同。对于非常大的迭代,这可能只会在开发模式中产生性能影响,如您所发现的那样。

请参阅https://stackoverflow.com/a/37356950/215945,了解与此相关的更深入的讨论&#34; devMode仅深入检查&#34;。