ReactiveX 学习笔记(22)使用 RxJS + Angular 进行 GUI 编程

课题

  1. 程序界面由3个文本编辑框和1个文本标签组成。
  2. 要求文本标签实时显示3个文本编辑框所输入的数字之和。
  3. 文本编辑框输入的不是合法数字时,将其值视为0。
  4. 3个文本编辑框的初值分别为1,2,3。

创建工程

# 安装 Angular CLI
$ npm install -g @angular/cli
# 创建新的应用程序 RxExample
$ ng new RxExample
$ cd RxExample
$ npm audit fix --force

打开 Intellij IDEA, File / New / Project From Existing Sources...,然后选中工程所在文件夹
在向导的第1页选择 Create project from existing sources
完成向导后在点击 Finish 创建工程。

点击 Add Configurations, 点击 +npm
Name: Angular CLI Server
Scripts: start
点击 OK 完成配置。
点击 Angular CLI Server 启动程序。
http://localhost:4200/ 可打开网页。

不使用 RxJS 的传统解决方案

打开 app.component.html 文件,将其改为

<div style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
</div>
<p>
  UI
  <input style="width:50px;text-align:right;" value="{{number1}}" (input)="onInputNumber()"> +
  <input style="width:50px;text-align:right;" value="{{number2}}" (input)="onInputNumber()"> +
  <input style="width:50px;text-align:right;" value="{{number3}}" (input)="onInputNumber()"> =
  <label>{{result}}</label><br>
</p>

打开 app.component.ts 文件,将其改为

import { Component, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {

  number1 = '1';
  number2 = '2';
  number3 = '3';
  result: string;

  title = 'RxExample';
  constructor() { }

  ngAfterViewInit() {
    this.onInputNumber();
  }

  onInputNumber() {
    const g = s => Number(s) || 0;
    this.result = String(g(this.number1) + g(this.number2) + g(this.number3));
  }
}

使用 RxJS 的解决方案

打开 app.component.html 文件,将其改为

<div style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
</div>
<p>
  <input #number1Ref style="width:50px;text-align:right;" value="1"> +
  <input #number2Ref style="width:50px;text-align:right;" value="2"> +
  <input #number3Ref style="width:50px;text-align:right;" value="3"> =
  <label>{{resultAsync | async}}</label>
</p>

打开 app.component.ts 文件,将其改为

import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { combineLatest, fromEvent, Observable } from 'rxjs';
import { map, pluck, startWith } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {

  @ViewChild('number1Ref') number1Ref: ElementRef;
  @ViewChild('number2Ref') number2Ref: ElementRef;
  @ViewChild('number3Ref') number3Ref: ElementRef;
  resultAsync: Observable<string>;

  title = 'RxExample';
  constructor() { }

  ngAfterViewInit() {
    const f = elemRef => fromEvent(elemRef.nativeElement, 'input')
      .pipe(pluck('target', 'value'), startWith((elemRef.nativeElement as HTMLInputElement).value));
    const g = s => Number(s) || 0;
    this.resultAsync = combineLatest(f(this.number1Ref), f(this.number2Ref), f(this.number3Ref))
      .pipe(map(results => String(g(results[0]) + g(results[1]) + g(results[2]))));
  }
}

猜你喜欢

转载自www.cnblogs.com/zwvista/p/9574484.html