如何获得 Angular 2/4 来更新现有 DOM 节点而不是删除+创建它们?
How do I get Angular 2/4 to update existing DOM nodes instead of deleting+creating them?
我的 Angular 4 应用程序有一个组件,它有一个 refresh
方法,可以从我的网络服务中拉入一个大对象,如下所示:
DTOs/Model 类型:
class NuclearReactorStatus {
public reactorName: string;
public coolingRods: CoolingRodStatus[]; // array of 1024 elements
}
class CoolingRodStatus {
public rodId : number;
public temperature: number;
public status : string;
}
里面NuclearReactorDisplayComponent
:
public reactorStatus: NuclearReactorStatus;
refresh(): void {
this.http.get<NuclearReactorStatus>()
.subscribe(
status => {
this.reactorStatus = status;
},
err => {
console.error( err );
}
);
}
在我的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>
我通过将杆 <li>
元素排列成网格来设计它们的样式:
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; }
注意我使用了transition: background-color
,所以钓竿框的背景颜色会逐渐变化,而不是突然变化。
当我 运行 我的程序时,我注意到 Angular 实际上 替换了 <ol>
和所有子 <li>
元素每次数据刷新而不是使用现有的 DOM 和更新 class
属性时 - 所以我的 background-color
转换永远不会发生 - 但更令人担忧的是 CPU 在我的计算机上的使用率猛增因为以这种方式操纵 DOM 的代价。
如何让 Angular 重新使用它在模板中创建的 <ol>
和 <li>
元素,而不是在每个刷新周期删除并重新创建它们?
由于ngFor
可能会在数据列表很大时表现不佳,Angular提供了一个trackBy
,你可以告诉angular 如何替换现有的 DOM 元素。查看详情 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;
}
我的 Angular 4 应用程序有一个组件,它有一个 refresh
方法,可以从我的网络服务中拉入一个大对象,如下所示:
DTOs/Model 类型:
class NuclearReactorStatus {
public reactorName: string;
public coolingRods: CoolingRodStatus[]; // array of 1024 elements
}
class CoolingRodStatus {
public rodId : number;
public temperature: number;
public status : string;
}
里面NuclearReactorDisplayComponent
:
public reactorStatus: NuclearReactorStatus;
refresh(): void {
this.http.get<NuclearReactorStatus>()
.subscribe(
status => {
this.reactorStatus = status;
},
err => {
console.error( err );
}
);
}
在我的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>
我通过将杆 <li>
元素排列成网格来设计它们的样式:
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; }
注意我使用了transition: background-color
,所以钓竿框的背景颜色会逐渐变化,而不是突然变化。
当我 运行 我的程序时,我注意到 Angular 实际上 替换了 <ol>
和所有子 <li>
元素每次数据刷新而不是使用现有的 DOM 和更新 class
属性时 - 所以我的 background-color
转换永远不会发生 - 但更令人担忧的是 CPU 在我的计算机上的使用率猛增因为以这种方式操纵 DOM 的代价。
如何让 Angular 重新使用它在模板中创建的 <ol>
和 <li>
元素,而不是在每个刷新周期删除并重新创建它们?
由于ngFor
可能会在数据列表很大时表现不佳,Angular提供了一个trackBy
,你可以告诉angular 如何替换现有的 DOM 元素。查看详情 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;
}