簡體   English   中英

angular2如何在`ngFor`中渲染一個計時器組件

[英]angular2 how do you render a timer Component inside `ngFor`

我想渲染一個視覺倒數計時器。 我正在使用這個組件, https://github.com/crisbeto/angular-svg-round-progressbar ,它依賴於SimpleChange來提供changes.current.previousValuechanges.current.currentValue

這是模板代碼

<ion-card  class="timer"
  *ngFor="let snapshot of timers | snapshot"
> 
  <ion-card-content>
    <round-progress 
      [current]="snapshot.remaining" 
      [max]="snapshot.duration"
      [rounded]="true"
      [responsive]="true"
      [duration]="800"
      >
    </round-progress>
</ion-card>

我正在使用此代碼來觸發angular2變化檢測

  this._tickIntervalHandler = setInterval( ()=>{
      // run change detection
      return;
    }
    // interval = 1000ms
    , interval
  )

更新 (經過大量測試,我發現問題不是我渲染時的精確度,而且這個問題已經改變以反映出來。)

問題是在1個變化檢測循環內多次調用ngFor 無論我的tick時間間隔或snapshot.remaining (即秒或十分之一秒)的精度如果在更改檢測期間后續調用ngFor時, snapshot.remaining發生更改,我都會收到異常:

Expression has changed after it was checked

如果我只渲染一個計時器而不使用ngFor那么更改檢測工作正常 - 即使是10ms間隔。

如何在頁面上渲染多個計時器,大概使用ngFor ,而不會觸發此異常?

經過一些測試后,似乎問題是使用帶有ngForSnapshotPipe來捕獲Timer數據的快照。 最終工作的是在View Component中獲取Timer數據的snapshot 如下面的答案所述,這使用pull方法來獲取更改,而不是push方法。

    // timers.ts
    export class TimerPage {
        // use with ngFor
        snapshots: Array<any> = [];

        constructor(timerSvc: TimerSvc){
            let self = this;
            timerSvc.setIntervalCallback = function(){
                self.snapshots = self.timers.map( (timer)=>timer.getSnapshot()  );
            }
        }

    }


    // timer.html
    <ion-card  class="timer"  *ngFor="let snapshot of snapshots"> 
    <ion-card-content>
        <round-progress 
        [current]="snapshot.remaining" 
        [max]="snapshot.duration"
        [rounded]="true"
        [responsive]="true"
        [duration]="800"
        >
        </round-progress>
    </ion-card>



    // TimerSvc can start the tickInterval
    export class TimerSvc {
        _tickIntervalCallback: ()=>void;
        _tickIntervalHandler: number;

        setIntervalCallback( cb: ()=>void) {
            this._tickIntervalCallback = cb;
        }

        startTicking(interval:number=100){
            this._tickIntervalHandler = setInterval( 
                this._tickIntervalCallback
                , interval
            );
        }
    }

第一個可疑的東西是toJSON (它有錯誤的名字或返回string或將字符串轉換為數組),哪些對象包含在timers數組中?

在更改期間,可能會多次評估循環,因此不應生成新對象。 另外toJSON管道應該標記為pure (參見Pipe decorator選項)。 此外,它是更好地提供trackBy的功能ngFor 通常,在這種情況下更好的是更新類字段而不是使用管道。


public snapshots:any[] = [];

private timers:any[] = [];

setInterval(()=>{
    this.snapshots = this.updateSnapshots(this.timers);
}, 100);

<ion-card  class="timer"
  *ngFor="let snapshot of snapshots"
> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM