变换操作符

1. scan

将上次的结果作为这下一次的初始值, 运算完进行发射。

1
2
3
4
5
6
7
8
const source$ = interval(1000).pipe(
      filter(val => val % 2 === 0),
      scan((oldVal, newVal) => oldVal + newVal),
      take(4)
    );

// 输出: '0', '2', '6', '12'
source$.subscribe(val => console.log(val));

数据流分析:

1
2
3
4
5
6
// scan的初始值为0, 每一次累加完的结果, 立马发射出去, 作为下一次的初始值进行累加
interval$: 0------1------2------3------4------5------6------
  filter$: 0-------------2-------------4-------------6------
                         \             \             \
                        0+2           2+4           6+6
    scan$: 0-------------2------------ 6-------------12-----

数据流图例:

2. reduce

reduce和scan比较相似, 唯一的不同点在于, reduce只是发射最终值。

1
2
3
4
5
6
7
8
const source$ = interval(1000).pipe(
      filter(val => val % 2 === 0),
      take(4),
      reduce((oldVal, newVal) => oldVal + newVal)
    );

// 输出: '12'
source$.subscribe(val => console.log(val));

数据流图例:

3. map

将源数据流中的元素,经过处理,映射成另一个元素。

1
2
3
4
5
6
7
8
// html
// 可以尝试用 div>input#length生成
<div><input type="text" id="length"></div>

// ts
const length = document.getElementById('length')
// 将输入的值*10
const source$ = fromEvent(length, 'keyup').pipe(map(ev => (ev.target as HTMLInputElement).value * 10));

数据流图例:

4. mapTo/pluck

pluck、mapTo是map的一种变形,可以通过map得到它们相对应的结果。

  • mapTo的作用在于,可以设置一个常量。比如button的click事件,我们不需要关心其值到底什么,我们只关心事件是否发生。
1
2
3
4
5
6
7
8
// html
// 可以尝试用 div>input#length生成
<div><input type="text" id="length"></div>

// ts
const length = document.getElementById('length')
// 无论输入什么值,都设置成"1"
const source$ = fromEvent(length, 'keyup').pipe(mapTo(1));
  • pluck获取控件的属性值,层级可以是二级、三级甚至更多。
1
2
3
4
5
6
7
8
// html
// 可以尝试用 div>input#length生成
<div><input type="text" id="length"></div>

// ts
const length = document.getElementById('length')
// 获取输入的值
const source$ = fromEvent(length, 'keyup').pipe(pluck('target', 'value'));