如何获取Angular 2/4来更新现有的DOM节点,而不是删除并创建它们? [英] How do I get Angular 2/4 to update existing DOM nodes instead of deleting+creating them?

查看:66
本文介绍了如何获取Angular 2/4来更新现有的DOM节点,而不是删除并创建它们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Angular 4应用程序具有一个组件,该组件具有refresh方法,该方法从我的Web服务中提取一个大对象,如下所示:

My Angular 4 application has a Component that has a refresh method that pulls-in a large object from my web-service, like so:

DTO/模型类型:

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>元素设置为网格样式:

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

请注意,我使用的是transition: background-color,因此标尺盒的背景颜色会逐渐变化,而不是突然变化.

Note my use of transition: background-color so the rod's box's background color changes gradually instead of suddenly.

在运行程序时,我注意到Angular每次刷新数据时实际上都会替换 <ol>和所有子<li>元素,而不是使用现有的DOM并更新class属性-因此我的background-color过渡永远不会发生-但更令人震惊的是,由于以这种方式操作DOM的开销,我的计算机上的CPU使用率飞速增长.

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.

如何让Angular重新使用在模板中创建的<ol><li>元素,而不是在每个刷新周期删除并重新创建它们?

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?

推荐答案

由于当数据列表很大时ngFor可能执行得不好,因此Angular提供了 trackBy ,您可以告诉angular如何替换现有的DOM元素.在 此处 中查看

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:

TrackByFun:

// assume you want to regenerate DOM element when rodId changed.
trackByFun(index: number, rod) { 
  return rod.rodId;               
}

这篇关于如何获取Angular 2/4来更新现有的DOM节点,而不是删除并创建它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆