[英]angular2 how do you render a timer Component inside `ngFor`
我想渲染一個視覺倒數計時器。 我正在使用這個組件, https://github.com/crisbeto/angular-svg-round-progressbar ,它依賴於SimpleChange
來提供changes.current.previousValue
和changes.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
,而不會觸發此異常?
解
經過一些測試后,似乎問題是使用帶有ngFor
的SnapshotPipe
來捕獲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.