我一直在玩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");
}
}
答案 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 blog,thoughtram blog,V.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;。