问题描述
我的 Angular 4 应用程序有一个具有 refresh
方法的组件,该方法从我的网络服务中提取一个大对象,如下所示:
DTO/模型类型:
class NuclearReactorStatus {公共反应器名称:字符串;公共冷却杆:CoolingRodStatus[];//1024个元素的数组}类 CoolingRodStatus {公共rodId:数字;公共温度:数字;公共状态:字符串;}
在NuclearReactorDisplayComponent
内部:
public reactorStatus:NuclearReactorStatus;刷新():无效{this.http.get().订阅(状态 =>{this.reactorStatus = 状态;},错误 =>{控制台错误(错误);});}
在我的 nuclearreactordisplay.component.html
Reactor {{reactorStatus.reactorName}}
<h2>冷却棒</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 </ol>
我正在通过将它们排列成网格来对杆 元素进行样式化:
ol {显示:弹性;flex-wrap: 包裹;列表样式:无;宽度:计算(32 * 16px);//网格是 32 个元素宽,32x32 == 1024}李{显示:块;宽度:16px;高度:16px;过渡:背景色0.2s;}里跨{显示:无;}li.cool { 背景色:黑色;}li.warm { 背景色:橙色;}li.hot { 背景色:黄色;}li.jalapeno { 背景色:红色;}
注意我使用了transition:background-color
,所以杆的盒子的背景颜色会逐渐变化而不是突然变化.
当我运行我的程序时,我注意到 Angular 实际上替换
- 和所有子
元素数据刷新而不是使用现有 DOM 并更新 class
属性 - 所以我的 background-color
转换从未发生 - 但更令人震惊的是我计算机上的 CPU 使用率猛增,因为以这种方式操作 DOM 的代价.我如何让 Angular 重新使用它在模板中创建的
- 和
元素,而不是删除并重新创建它们刷新周期?由于 ngFor
在数据列表很大时可能会执行不好,Angular 提供了一个 trackBy
您可以告诉 angular 如何替换现有的 DOM 元素.在此处查看详细信息.
<li *ngFor="let rod of reactorStatus.coolingRods; trackBy: trackByFun"[data.rod-id]="rod.rodId"[data.rod-temperature]="rod.temperature" class="{{ rod.temperature <span>{{rod.rodId}}</span></ol>
TrackByFun:
//假设您想在 rodId 更改时重新生成 DOM 元素.trackByFun(索引:数字,杆){返回rod.rodId;}
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?
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;
}
这篇关于如何让 Angular 2/4 更新现有的 DOM 节点而不是删除+创建它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!