问题
My Angular 4 application has a Component that has a refresh method that pulls-in a large object from my web-service, like so:
DTOs/Model types:
class NuclearReactorStatus {
public reactorName: string;
public coolingRods: CoolingRodStatus[]; // array of 1024 elements
}
class CoolingRodStatus {
public rodId : number;
public temperature: number;
public status : string;
}
Inside the NuclearReactorDisplayComponent:
public reactorStatus: NuclearReactorStatus;
refresh(): void {
this.http.get<NuclearReactorStatus>()
.subscribe(
status => {
this.reactorStatus = status;
},
err => {
console.error( err );
}
);
}
Inside my nuclearreactordisplay.component.html
<h1>Reactor {{reactorStatus.reactorName}}</h1>
<h2>Cooling rods</h2>
<ol *ngIf="reactorStatus.coolingRods">
<li *ngFor="let rod of reactorStatus.coolingRods"
[data.rod-id]="rod.rodId"
[data.rod-temperature]="rod.temperature"
class="{{ rod.temperature < 100 ? "cool" : rod.temperature < 1000 ? "warm" : rod.temperature < 10000 ? "hot" : "jalapeno" }}"
>
<span>{{rod.rodId}}</span>
</li>
</ol>
I'm styling the rod <li> elements by arranging them into a grid:
ol {
display: flex;
flex-wrap: wrap;
list-style: none;
width: calc( 32 * 16px ); // grid is 32 elements wide, 32x32 == 1024
}
li {
display: block;
width: 16px;
height: 16px;
transition: background-color 0.2s;
}
li span {
display: none;
}
li.cool { background-color: black; }
li.warm { background-color: orange; }
li.hot { background-color: yellow; }
li.jalapeno { background-color: red; }
Note my use of transition: background-color so the rod's box's background color changes gradually instead of suddenly.
When I run my program, I notice that Angular actually replaces the <ol> and all child <li> elements each time the data refreshes instead of using the existing DOM and updating the class attributes - so my background-color transition never happens - but more alarmingly the CPU usage on my computer skyrockets because of the expense of manipulating the DOM this way.
How do I get Angular to re-use the <ol> and <li> elements it created in the template instead of deleting and recreating them on every refresh cycle?
回答1:
Since ngFor may preform bad when the data list is huge, Angular has provided a trackBy which you can tell angular how to replace existing DOM elements. See details here.
<ol *ngIf="reactorStatus.coolingRods">
<li *ngFor="let rod of reactorStatus.coolingRods; trackBy: trackByFun"
[data.rod-id]="rod.rodId"
[data.rod-temperature]="rod.temperature" class="{{ rod.temperature < 100 ? "cool" : rod.temperature < 1000 ? "warm" : rod.temperature < 10000 ? "hot" : "jalapeno" }}">
<span>{{rod.rodId}}</span>
</li>
</ol>
TrackByFun:
// assume you want to regenerate DOM element when rodId changed.
trackByFun(index: number, rod) {
return rod.rodId;
}
来源:https://stackoverflow.com/questions/46249811/how-do-i-get-angular-2-4-to-update-existing-dom-nodes-instead-of-deletingcreati