使用 *ngFor 时如何避免 :enter/:leave 动画值变化?

How to avoid :enter/:leave animations on value change when using *ngFor?

我正在使用 angular 9 和 angular material。 我有我想要编辑的动态字符串列表 - 每个都在一个单独的输入中。 我也希望能够添加和删除它们,并为此添加一些动画。

问题: :enter 和 :leave 动画在每次值更改时触发。

Stackblitz:https://stackblitz.com/edit/angular-material-baseline2-7pmidv

到目前为止,我想到的最佳解决方案是使用单独的对象来存储值。

public list:{value:string}[] = [{value: "1"}, {value: "2"}, {value:"3"}];

而不是

public list: string[] = ["1", "2", "3"];

我想知道是否有更好的方法。

那是因为 ngFor 的内部运作方式。一旦被跟踪元素的引用发生变化 ngFor 将重新呈现它。

由于 javascript 不会在堆栈上保存对基元的引用,而是直接保存值,因此每次值更改都会更改堆栈上的值,因此 ngFor 将重新渲染您的对象。

因此,如果您将其包装在一个对象中并且仅更改对象值,则不会发生引用更改,这就是您的解决方案有效的原因。

但是为了防止这种情况,Angular 提供了 trackByFn。此函数允许您为对象定义唯一标识符,如果标识符保持不变,即使 reference/value 更改,您的对象也不会重新呈现。所以我认为你最好的选择是使用索引作为唯一标识符:

打字稿:

  trackItem(index:number,item:string){
    return index;
  }

HTML:

<div  [@inOutAnimation] *ngFor="let val of list; index as i;trackBy:trackItem" class="form-field">
    <mat-form-field >
      <mat-label>At</mat-label>
      <input matInput [(ngModel)] = "list[i]">
    </mat-form-field>
    <button mat-icon-button class="add-shift-btn" (click)="removeShift(i)">
      <mat-icon aria-hidden="false" aria-label="Example home icon">delete</mat-icon>
    </button>
   </div>