angular2如何在"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
)

更新(经过大量测试,我发现问题不在于我渲染的时间的准确性,这个问题已经改变以反映这一点。)

问题是ngFor在一个变化检测循环内被多次调用。无论我的刻度间隔或snapshot.remaining的精度如何(即秒或十分之几秒),如果snapshot.remaining在更改检测过程中对ngFor的后续调用中发生更改,我都会得到一个异常:

Expression has changed after it was checked

如果我只渲染一个计时器而不使用ngFor,那么更改检测工作得很好——即使对于10ms的间隔也是如此。

如何在一个页面上呈现多个计时器,大概使用ngFor,而不触发此异常?

解决方案

经过一点测试,问题似乎是使用SnapshotPipengFor来捕获Timer数据的快照。最终起作用的是在视图组件中获取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(请参见管道装饰器选项)。此外,最好为ngFor提供trackBy功能。通常,在这种情况下,最好更新类字段,而不是使用管道。


public snapshots:any[] = [];
private timers:any[] = [];
setInterval(()=>{
this.snapshots = this.updateSnapshots(this.timers);
}, 100);
<ion-card  class="timer"
*ngFor="let snapshot of snapshots"
> 

相关内容

  • 没有找到相关文章

最新更新