在角1我们避免了从超过模板表达式,如内部调用函数ng-repeat="item in vm.getFilteredItems()",因为属性更改无关的结果getFilteredItems会导致功能重复和不必要的重新计算的消化,这通常会导致性能问题的规模.相反,我们绑定到对象,并基于事件(例如ng-repeat="item in vm.filteredItems)进行计算.
在Angular 2中,脏检查过程已经过优化,但是当组件级别的任何属性发生更改时,仍会调用组件模板中调用的函数,无论该函数是否依赖于这些属性.如果使用不当,我预计这会导致相同的性能问题.
以下是Angular 2中不同方法的简化示例:
// function binding in template
@Component({
selector: 'func',
template: `
<input [(ngModel)]="searchTerm" placeholder="searchTerm" />
<div *ngFor="let name of filteredNames(searchTerm)">{{name}}</div>
`
})
export class FuncComponent {
@Input() names:string[];
filteredNames(searchTerm) {
if (!searchTerm) return this.names;
let filteredNames = [];
return this.names.filter((name) => {
return name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;
});
}
}
Run Code Online (Sandbox Code Playgroud)
-
// no function binding
@Component({
selector: 'nofunc',
template: `
<input [(ngModel)]="searchTerm" (ngModelChange)="search($event)" placeholder="searchTerm" />
<div *ngFor="let name of filteredNames">{{name}}</div>
`
})
export class NoFuncComponent implements OnInit {
@Input() names:string[];
searchTerm: string;
ngOnInit() {
this.search(this.searchTerm);
}
search() {
if (!this.searchTerm) {
this.filteredNames = this.names;
return;
}
this.filteredNames = this.names.filter((name) => {
return name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1;
});
}
}
Run Code Online (Sandbox Code Playgroud)
http://plnkr.co/edit/AAFknlJgso3D8F1w3QC1?p=preview
这在Angular 2中仍然是一个问题吗?哪种方法更受欢迎,为什么?谢谢!
你可以创建一个管道.管道(if pure)仅在依赖值更改时调用.
@Pipe({
name: 'search',
// pure: 'false'
})
class SearchPipe {
transform(names, searchTerm) {
if (!this.searchTerm) {
this.filteredNames = names;
return;
}
return names.filter((name) => {
return name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1;
});
}
}
@Component({
selector: 'func',
pipes: [SearchPipe],
template: `
<input [(ngModel)]="searchTerm" placeholder="searchTerm" />
<div *ngFor="let name of names | search:searchTerm">{{name}}</div>
`
})
export class FuncComponent {
@Input() names:string[];
}
Run Code Online (Sandbox Code Playgroud)
如果管道需要识别更改,names则pure需要禁用.
如果names是由不同的实例,而不是仅仅被成员添加或删除替换,然后pure工作正常,管道只执行时names或searchTerm变化.
暗示
在devMode(默认)更改检测运行两次,管道将被调用两倍于预期.