2016-06-07 9 views
8

In Angular 1 vermieden wir den Aufruf von Funktionen innerhalb von Vorlagenausdrücken im Überschuß, z. ng-repeat="item in vm.getFilteredItems()", da Eigenschaftsänderungen, die nichts mit dem Ergebnis von getFilteredItems zu tun haben, dazu führen würden, dass die Funktion wiederholt und unnötigerweise bei Digests neu berechnet wird, was häufig Leistungsprobleme im Maßstab verursacht. Stattdessen binden wir an Objekte und berechnen basierend auf Ereignissen (z. B.). In Angular 2 wurde der Dirty-Checking-Prozess optimiert, aber in Component Templates aufgerufene Funktionen werden immer noch aufgerufen, wenn sich Eigenschaften auf Komponentenebene ändern, unabhängig davon, ob die Funktion von diesen Eigenschaften abhängig ist. Ich erwarte, dass dies bei unsachgemäßer Verwendung zu den gleichen Leistungsproblemen führen kann.Angular 2: Bindung an Funktionen von Komponentenvorlagen

Hier ist ein vereinfachtes Beispiel für die unterschiedlichen Ansätze in 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; 
    }); 
    } 
} 

-

// 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; 
    }); 
    } 
} 

http://plnkr.co/edit/AAFknlJgso3D8F1w3QC1?p=preview

Dies ist immer noch ein Problem in Angular 2? Welcher Ansatz wird bevorzugt und warum? Vielen Dank!

Antwort

5

Sie könnten eine Rohrleitung erstellen. Pipes (wenn pure) werden nur aufgerufen, wenn sich die abhängigen Werte ändern.

@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[]; 
} 

Wenn das Rohr Änderungen in names erkennen muss, dann muss pure deaktiviert sein.

Wenn names durch eine andere Instanz ersetzt wird, anstatt nur Mitglieder hinzugefügt oder entfernt werden, dann funktioniert pure fein und das Rohr wird nur ausgeführt, wenn names oder searchTerm Änderungen.

Hint

In devMode (Standard) Änderungserkennung läuft zweimal und das Rohr wird doppelt so viel wie erwartet, genannt werden.

Verwandte Themen