【问题标题】:How do I get Angular 2/4 to update existing DOM nodes instead of deleting+creating them?如何让 Angular 2/4 更新现有的 DOM 节点而不是删除+创建它们?
【发布时间】:2017-09-16 03:42:46
【问题描述】:

我的 Angular 4 应用程序有一个组件,它有一个 refresh 方法,可以从我的网络服务中拉入一个大对象,如下所示:

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>

我通过将杆&lt;li&gt; 元素排列成网格来设置它们的样式:

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 实际上替换 &lt;ol&gt; 和所有子 &lt;li&gt; 元素每次刷新数据时,而不是使用现有的 DOM 并更新 class属性 - 所以我的 background-color 转换永远不会发生 - 但更令人担忧的是,由于以这种方式操作 DOM 的代价,我的计算机上的 CPU 使用率飙升。

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

【问题讨论】:

    标签: angular angular2-template


    【解决方案1】:

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

    【讨论】:

    • 谢谢。这成功了,现在我的页面刷新得像黄油一样光滑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    相关资源
    最近更新 更多