【问题标题】:Angular 2 - Countdown timerAngular 2 - 倒数计时器
【发布时间】:2017-11-13 08:21:06
【问题描述】:

我愿意在 Angular 2 中做一个从 60 开始的倒数计时器(即 59、58,57 等...)

为此,我有以下几点:

constructor(){
  Observable.timer(0,1000).subscribe(timer=>{
  this.counter = timer;
});
}

以上,每秒滴答一次,这很好;但是,它会按升序排列到无限数量。 我不确定是否有办法调整它,以便我可以有一个倒计时。

【问题讨论】:

    标签: angular rxjs countdown countdowntimer


    【解决方案1】:

    有很多方法可以实现,一个基本的例子是使用take操作符

    import { Observable, timer } from 'rxjs';
    import { take, map } from 'rxjs/operators';
    
    @Component({
       selector: 'my-app',
       template: `<h2>{{counter$ | async}}</h2>`
    })
    export class App {
       counter$: Observable<number>;
       count = 60;
    
       constructor() {
         this.counter$ = timer(0,1000).pipe(
           take(this.count),
           map(() => --this.count)
         );
       }
    }
    

    更好的方法是创建一个计数器指令!

    import { Directive, Input, Output, EventEmitter, OnChanges, OnDestroy } from '@angular/core';
    
    import { Subject, Observable, Subscription, timer } from 'rxjs';
    import { switchMap, take, tap } from 'rxjs/operators';
    
    @Directive({
      selector: '[counter]'
    })
    export class CounterDirective implements OnChanges, OnDestroy {
    
      private _counterSource$ = new Subject<any>();
      private _subscription = Subscription.EMPTY;
    
      @Input() counter: number;
      @Input() interval: number;
      @Output() value = new EventEmitter<number>();
    
      constructor() {
    
        this._subscription = this._counterSource$.pipe(
          switchMap(({ interval, count }) =>
            timer(0, interval).pipe(
              take(count),
              tap(() => this.value.emit(--count))
            )
          )
        ).subscribe();
      }
    
      ngOnChanges() {
        this._counterSource$.next({ count: this.counter, interval: this.interval });
      }
    
      ngOnDestroy() {
        this._subscription.unsubscribe();
      }
    
    }
    

    用法:

    <ng-container [counter]="60" [interval]="1000" (value)="count = $event">
      <span> {{ count }} </span>
    </ng-container>
    

    这里是直播stackblitz

    【讨论】:

    • 从组合的可观察对象中改变外部状态很少是一个好主意,在这里它是不必要的。另一种选择:Observable.timer(0, 1000).map(value =&gt; 60 - value).takeWhile(value =&gt; value &gt; 0)
    • @cartant 这不是一个状态。它只是一个倒计时
    • 当计数器达到 0 时,我怎么能做到这一点,它会重新计数到 10。我的意思是在我的显示器中。我用来显示数字 10 并将开始倒计时到 9 ,8 ,7 ,6 ,5 ,4.. 等等,直到它达到 0。当它达到零时,它会再次开始倒计时到 10。
    • @JydonMah 有一个repeat() 操作符可以在链的末端使用
    • 感谢这个人,我将它添加到代码的末尾,但它继续为负值。你能为它提供工作示例吗?我似乎很难弄清楚。顺便说一句,我只是角度和打字稿的新手:)
    【解决方案2】:

    导入组件:

    import { Observable } from "rxjs/Observable";
    import "rxjs/add/observable/timer";
    import "rxjs/add/operator/finally";
    import "rxjs/add/operator/takeUntil";
    import "rxjs/add/operator/map";
    

    功能倒计时:

    countdown: number;
     startCountdownTimer() {
        const interval = 1000;
        const duration = 10 * 1000;
        const stream$ = Observable.timer(0, interval)
          .finally(() => console.log("All done!"))
          .takeUntil(Observable.timer(duration + interval))
          .map(value => duration - value * interval);
        stream$.subscribe(value => this.countdown = value);
      }
    

    HTML:

    <div class="panel panel-default">
      <div class="panel-heading">
        <h2 class="panel-title">Countdown timer</h2>
      </div>
      <div class="panel-body">
        <div>
          <label>value: </label> {{countdown}}
        </div>
        <div>
          <button (click)="startCountdownTimer()" class="btn btn-success">Start</button>
        </div>
      </div>
    </div>
    

    【讨论】:

    • 如何停止计时器?
    • @Asif 通过取消订阅 "stream$" observable。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多