0

https://www.learnrxjs.io/recipes/smartcounter.html,我找到了 Angular 2+ 中数字计数器的一个很好的示例,代码如下所示:

@Component({
  selector: 'number-tracker',
  template: `
    <h3> {{ currentNumber }}</h3>
  `
})
export class NumberTrackerComponent implements OnDestroy {
  @Input()
  set end(endRange: number) {
    this._counterSub$.next(endRange);
  }
  public currentNumber = 0;
  private _counterSub$ = new Subject();
  private _subscription : Subscription;

  constructor() {
    this._subscription = this._counterSub$
      .switchMap(endRange => {
        return timer(0, 20)
            .mapTo(this.positiveOrNegative(endRange, this.currentNumber))
            .startWith(this.currentNumber)
            .scan((acc, curr) => acc + curr)
            // .delayWhen(i => {
            //   easing here
            // })
            .takeWhile(this.takeUntilFunc(endRange, this.currentNumber));
      })
      .subscribe(val => this.currentNumber = val);
  }

  private positiveOrNegative(endRange, currentNumber) {
    return endRange > currentNumber ? 1 : -1;
  }

  private takeUntilFunc(endRange, currentNumber) {
    return endRange > currentNumber
      ? val => val <= endRange
      : val => val >= endRange;
  }

  ngOnDestroy() {
    this._subscription.unsubscribe();
  }
}

现在这很好用,但我想传递一个变量 currentNumber 而不是 this.currentNumber 默认 0。

到目前为止,我已经走了这么远:

  public currentNumber: number;
...    
  @Input()
  set fanCountPrev(startRange: number) {
    this.currentNumber = startRange
    console.log('startRange: ', this.currentNumber)
  }

...

但是当一个新值到达时,this.currentNumber 没有设置为以前的版本。

您有任何提示或示例来完成此操作吗?

4

1 回答 1

0

这里的问题是订阅是在构造函数上进行的,而 Input() 绑定是在 ngOnInit lifehook 上解决的。此外,在这种情况下,在运行时手动修改 this.currentNumber 变量并不是一个好习惯,因此可观察计算的内部状态也是如此。我认为唯一可行的方法是在 onInit 上对其进行修改,为此,正如我所说,您必须在 ngOnInit lifehook 函数中创建订阅,如下所示:

@Component({
  selector: 'number-tracker',
  template: `
    <h3> {{ currentNumber }}</h3>
  `
})
export class NumberTrackerComponent implements OnDestroy {
  @Input()
  set end(endRange: number) {
    this._counterSub$.next(endRange);
  }
  @Input()
  set fanCountPrev(startRange: number) {
    this.currentNumber = startRange
    console.log('startRange: ', this.currentNumber)
  }
  private currentNumber = 0;
  private _counterSub$ = new Subject();
  private _subscription : Subscription;

  constructor() {
    
  }
  
  ngOnInit() {
    this._subscription = this._counterSub$
      .switchMap(endRange => {
        return timer(0, 20)
            .mapTo(this.positiveOrNegative(endRange, this.currentNumber))
            .startWith(this.currentNumber)
            .scan((acc, curr) => acc + curr)
            // .delayWhen(i => {
            //   easing here
            // })
            .takeWhile(this.takeUntilFunc(endRange, this.currentNumber));
      })
      .subscribe(val => this.currentNumber = val);
  }

  private positiveOrNegative(endRange, currentNumber) {
    return endRange > currentNumber ? 1 : -1;
  }

  private takeUntilFunc(endRange, currentNumber) {
    return endRange > currentNumber
      ? val => val <= endRange
      : val => val >= endRange;
  }

  ngOnDestroy() {
    this._subscription.unsubscribe();
  }
}

但请记住,此解决方案仅适用于初始化。如果您在此组件存在期间更改变量,这将不起作用。但正如我所说,在这种情况下这不是一个好习惯,因为它是组件的内部计算状态,它仅在初始化时才有意义。

希望这可以帮助。

于 2017-11-06T23:25:21.067 回答