angular的学习进阶(十七)


虚拟滚动条

资料

响应式应用

https://responsively.app/download

有趣的代码

https://1loc.dev/

rxjs 运算符相互的区别

export type Shape = '1' | '2';
export type Card = '3' | '4';
 public shapes$ = new Subject<Shape>();
 public cards$ = new Subject<Card>();

zip 每次压缩的可观察值,一组一组发

    zip(of(1),of(2)).subscribe(console.log)

ngOnInit(): void {
    zip(this.shapes$, this.cards$).subscribe(console.log);
    this.shapes$.next('1');
    this.cards$.next('3');

    this.shapes$.next('2');
    this.cards$.next('3');

    this.shapes$.next('1');
    this.cards$.next('4');
    // 不需要complete 也能执行
  }
  
  ["1", "3"] 
  ["2", "3"]
  ["1", "4"]

forkJoin 仅在完成之后才发出最后一组的值

    forkJoin(of(1),of(2)).subscribe(console.log)
	[1,2]

ngOnInit(): void {
    forkJoin(this.shapes$, this.cards$).subscribe(console.log);
    this.shapes$.next('1');
    this.cards$.next('3');

    this.shapes$.next('2');
    this.cards$.next('3');

    this.shapes$.next('1');
    this.cards$.next('4');
    // 在complete完成后才会执行
    this.shapes$.complete()
    this.cards$.complete()
  }
  
  ["1", "4"]

combineLatest 每次可观察对象发出新值,会发出之前的值

 ngOnInit(): void {
    combineLatest(this.shapes$, this.cards$).subscribe(console.log);
    this.shapes$.next('1');
    this.cards$.next('3');
	// 2次
    this.shapes$.next('2');
    this.cards$.next('3');
	// 2次
    this.shapes$.next('1');
    this.cards$.next('4');
	//1 次
	// 不需要complete
}
//  ["1", "3"]
//  ["2", "3"]
// ["2", "3"]
// ["1", "3"]
// ["1", "4"]

distinctUntilChanged 运算符

number,string

 [1, 2, 3, 1, 3]   of(1, 1, 2, 2, 3, 3, 1, 3, 3, 3).pipe(distinctUntilChanged(), toArray()).subscribe(console.log);
   // [1, 2, 3, 1, 3]
    of('a', 'A', 'b', 'c', 'D', 'd', 'e', 'f', 'G', 'g', 'h').pipe(
      // 把前一个字和后一个值转化成小写,所以相同的就可以跳过
      // c ,p 可以理解成前一个值,后一个值
      distinctUntilChanged((c, p) => c.toLowerCase() === p.toLowerCase()),
      toArray()
    ).subscribe(console.log);
  //  ["a", "b", "c", "D", "e", "f", "G", "h"]

对象流

将对对象引用的比较,而不是对象属性值得比较

 from([obj,obj,obj]).pipe(distinctUntilChanged()).subscribe(console.log)
  // {name: "xxx"}

但是我们写成函数进行判断

   from([
      { name: 'Porsche', model: '911' },
      { name: 'Porsche', model: '911' },
      { name: 'Ferrari', model: 'F40' }
    ]).pipe(
      distinctUntilChanged((p,n)=>{
        return p.name===n.name&&p.model===n.model
      }),
    ).subscribe(console.log)
// {name: "Porsche", model: "911"}
//  {name: "Ferrari", model: "F40"}

两个参数的情况

 from([
      { name: 'Porsche', model: '911' },
      { name: 'PORSCHE', model: '911' },
      { name: 'Ferrari', model: 'F40' },
      { name: 'FERRARI', model: 'F40' },
    ]).pipe(
      distinctUntilChanged(
        (p,n)=>{
        return p.toLowerCase()===n.toLowerCase()
      },/*第二个函数你可以理解成 c=>v.name
        :{}  我差点蒙蔽了,其实就是做了typescript做的类型限制
      */
        (car:{name:string,model:string})=>car.name
      ),
    ).subscribe(console.log)
   // {name: "Porsche", model: "911"}
   // {name: "Ferrari", model: "F40"}

源码地址

官方用法地址

封装input 延迟输入指令

ng g d delayed/delayed-input
import {Directive, OnInit,OnDestroy,ElementRef, EventEmitter, Input, Output} from '@angular/core';
import {from, fromEvent, Subject, timer} from 'rxjs';
import {debounce, distinctUntilChanged, takeUntil} from 'rxjs/operators';

@Directive({
  selector: '[appDelayedInput]'
})
export class DelayedInputDirective implements OnInit,OnDestroy{
  // 声明的 destroy$,配合 takeUntil 运算符一起使用,当指令销毁时,取消订阅
  private destroy$ = new Subject<void>();
  // debounce 配合timer 使用 500ms发出一个值
  @Input() delayTime = 500;
  @Output() delayedInput = new EventEmitter<Event>();
  // 拿到DOM
  constructor(private elementRef: ElementRef<HTMLInputElement>) {
  }

  ngOnInit() :void{
    fromEvent(this.elementRef.nativeElement,'input').pipe(
      debounce(()=>timer(this.delayTime)),
      distinctUntilChanged(null,
        (event:Event)=>(event.target as HTMLInputElement).value
        ),
      takeUntil(this.destroy$)
    ).subscribe(e=>this.delayedInput.emit(e))
  }

  ngOnDestroy() {
    this.destroy$.next();
  }
}

使用

  <input type="text" appDelayedInput [delayTime]="600" (delayedInput)="search($event)">

 search(event: Event) {
    console.log((event.target as HTMLInputElement).value);
  }

rxjs publish() 冷热处理

 let a = interval(1000).pipe(
      tap(v => console.log('打印下'+v)),
      take(5),
      // 冻住
      publish()
    ) as ConnectableObservable<number>


    a.subscribe(res => {
      console.log(res);
    }, err => {

    }, () => {
      console.log('再见');
    });
    // 解除
      a.connect();

// 打印下0
// 0
// 打印下1
// 1
// 打印下2
// 2
// 打印下3
// 3
// 打印下4
// 4
// 再见

rxjs delayWhen

 of(10).pipe(delayWhen(_=>timer(1000))).subscribe(res=>{
      console.log(res);
    })
    // 延迟传递值, 传递的参数是一个函数,这种方法好像比较实用

合并

 let a=interval(1000).pipe(take(4))
 let b=interval(1000).pipe(take(2))

zip

    zip(a,b).subscribe(console.log)
// [ 0, 0]
// [ 1, 1]

最小分母数

merge

    merge(a,b).subscribe(console.log)
// 0 两次
// 1 两次
// 1
// 2
// 3

concat

    concat(a,b).subscribe(console.log)
// 0
// 1
// 2
// 3
// 0 
// 1

rxjs 运算

// 观察每次状态的改变
of(1,2,3,4,5).pipe(scan((acc,val)=>acc+val,0)).subscribe(console.log)
    // 1
    // 3
    // 6
    // 10
    // 15
// 计算点击的次数
fromEvent(this.ccc.nativeElement,'click').pipe(scan((acc,val)=>++acc,0)).subscribe(console.log)

of(1,2,3,4,5).pipe(max()).subscribe(console.log)
// 5
of(1,2,3,4,5).pipe(min()).subscribe(console.log)
// 1    
of(1,2,3,4,5).pipe(reduce((acc,val)=>acc+val)).subscribe(console.log)
// 15
of({ name : 'chris' },{ age : 11 }).pipe(
      reduce((acc,curr) => ({ ...acc, ...curr}))
    ).subscribe(console.log)
    // {name: "chris", age: 11}

rxjs buffer缓冲

  interval(200).pipe(
      buffer(timer(1000))
    ).subscribe(console.log)
// [0,1,2,3]
//值发生一次

interval(1000).pipe(
      buffer(interval(4000))
    ).subscribe(console.log)
// [0, 1, 2]
// [3, 4, 5, 6]
//  [7, 8, 9, 10]
// bufferWhen 参数函数 可以用数组长度看相隔多少s点击一次
 interval(1000).pipe(
      bufferWhen(() => fromEvent(this.ccc.nativeElement, 'click'))
    ).subscribe(console.log);

buferCount

收集缓冲区并在指定数量的值后,作为数组发出

   const src$ = merge(
      of(1).pipe(delay(1000)),
      of(2).pipe(delay(4000)),
      of(3).pipe(delay(5000)),
    );
    src$.pipe(
      bufferCount(3)
    ).subscribe(console.log)

=============
interval(1000).pipe(
      bufferCount(3)
    ).subscribe(console.log)
// [0,1,2]
// [3,4,5]
// [6,7,8]
posted @ 2020-08-18 10:46  猫神甜辣酱  阅读(367)  评论(0编辑  收藏  举报