Angular 5 - 基本计时器对象未在 UI 中更新

Angular 5 - Basic timer object not updating in the UI

我正在开发内置于 Angular 5 的应用程序,它需要一个基本的 mm:ss 倒数计时器,最终将动态设置。我尝试过许多不同的解决方案,但所有的解决方案都以相同的方式运行。

我开始硬编码只是为了得到它 运行,并添加了一个基本功能:

time: number = 60;
interval;

startTimer() {
    this.interval = setInterval(() => {
        if (this.time > 0) {
            this.time--;
        } else {
            this.time = 60;
        }
    }, 1000)
}

在前端,我用一个按钮调用函数:

<button (click)='startTimer()'>Start Timer</button>
<p>{{ time }} seconds remaining....</p>

页面加载完成后,可以看到数字60。但它并没有倒计时。当您按下按钮时,数字会更改为最多的秒数。例如,它会显示 60,2 秒后单击它,数字将变为 58。所以计时器是 运行 背景,但数字在 UI.[=14 中没有更新=]

我是 Angular 的新手,所以我可能正在考虑一些基本的东西。我见过其他需要创建管道或订阅的解决方案,但我尝试过的所有解决方案似乎都以与此相同的方式运行。任何指针将不胜感激!

我认为使用 RxJS 比 setInterval() 方法更好。使用 RxJS timer 函数和 takemap 运算符尝试以下操作。

控制器

timer$: Observable<number>;

startTimer(counter: number) {
  this.timer$ = timer(0, 1000).pipe(
    take(counter),
    map(_ => --counter)
  );
}

模板

<input type="number" #timeInput placeholder="Enter time in seconds"/><br>
<button (click)='startTimer(timeInput.value)'>Start Timer</button>

<ng-container *ngIf="(timer$ | async) as timer">
  <p>{{ timer }} seconds remaining....</p>
</ng-container>

工作示例:Stackblitz

更新:旧版本的 RxJS (<=v5)

RxJS 函数和运算符的导入和使用存在明显差异 b/n v5+ 和 v6+。以下内容适用于 RxJS v5.

控制器

import 'rxjs/add/observable/timer';

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';

timer$: any;

startTimer(counter: number) {
  this.timer$ = Observable.timer(0, 1000).take(counter).map(_ => --counter);
}

模板

<input type="number" #timeInput placeholder="Enter time in seconds"/><br>
<button (click)='startTimer(timeInput.value)'>Start Timer</button>

<ng-container *ngIf="(timer$ | async) as timer">
  <p>{{ timer }} seconds remaining....</p>
</ng-container>

另一种使用 RxJs 的方法

// imports
import { interval, Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';

...
// inside your component
timeout$: Observable<number>;

setCountdown(time = 60) {
  this.timeout$ = interval(1000).pipe(
    take(time),
    map(t => time - t - 1)
  );
}

<button (click)='startTimer()'>Start Timer</button>
<p>{{ timeout$ | async }} seconds remaining....</p>

试试这个选项:

startTimer() {
    this.interval = setInterval(() => {
      if (this.time > 0) {
        this.time -= 10;
      } else {
        clearInterval(this.interval);
        this.time = 60;
      }
    }, 1000)
  }