Angular 2 - 使用ngFor,是否可以在不重建dom的情况下更新值?

seb*_*bap 16 angular

我在ngFor中有一个组件'bar'.我想用动画从前一个值开始更新它的宽度到新的宽度.

HTML:

<div *ngFor="let station of stations" class="station">
    <bar [perc]="station.perc" class="bar"></bar>
</div>
Run Code Online (Sandbox Code Playgroud)

ParentComponent:

ngOnInit(){
    setInterval(() => this.updateData(), 10000);
  }

  updateData(){
    const url = 'http://....';
    this.http.get(url)
      .map(res => res.json())
      .subscribe(data => {

        this.stations = data;

      });
  }
Run Code Online (Sandbox Code Playgroud)

BarComponent

export class BarComponent {

  @Input() perc;

  constructor(private element: ElementRef){}

  ngOnChanges(changes: any): void {
    let perc = changes.perc.currentValue;
    TweenMax.to(this.element.nativeElement, 1, { width: perc + '%' });
  }

}
Run Code Online (Sandbox Code Playgroud)

但是在每个updateData()上,它看起来像ngFor重新创建dom并再次构造BarComponent.因此,即使'station.perc'相同,也会触发ngOnChanges().

并且转换从0开始重新开始,而不是从之前的值开始...

我可能在这里错过了一个关键点但是干净的解决方法是什么?

yur*_*zui 28

我猜你应该使用trackByoption来自定义ngFor指令的默认跟踪算法:

视图

<div *ngFor="let station of stations; let i = index; trackBy: trackByFn" class="station">
  <bar [perc]="station.perc" class="bar"></bar>
</div>
Run Code Online (Sandbox Code Playgroud)

零件

trackByFn(index, item) {
  return index;
}
Run Code Online (Sandbox Code Playgroud)

或者更好地使用唯一ID:

trackByFn(index, station) {
  return station.id;
}
Run Code Online (Sandbox Code Playgroud)

在这里查看有关trackBy的更多详细信息:

Hope Plunker Example也将为您提供帮助.