• angular学习进阶(十五)


    resolve(解决守卫)

    保证了数据获取后在进行路由跳转,防止因为数据延迟而出现的空组件情况

    简单的理解成解决延迟守卫

    创建一个接口

    product/product.ts
    ng g i product/product.ts
    
    export interface Product {
      id: number;
      name: string;
      price: number
    }
    

    创建一个服务

    ng g s product/product

    import {Injectable} from '@angular/core';
    import {Observable, of} from 'rxjs';
    import {Product} from './product';
    import {delay} from 'rxjs/internal/operators/delay';
    import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router';
    
    @Injectable({
      providedIn: 'root'
    })
    export class ProductService implements Resolve<Product[]> {
    
      constructor() {
      }
    // 模拟请求
      getList(): Observable<Product[]> {
        return of([
          {id: 12, name: 'sss', price: 124},
          {id: 13, name: 'xxx', price: 1231},
          {id: 14, name: 'bbb', price: 132},
        ]).pipe(delay(2000));
      }
    
    // 把请求放在延迟函数中
      resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Product[]> | Promise<Product[]> | Product[] {
        return this.getList();// 可以对这个值进行二次加工
      }
    }
    
    

    app-routing.module

     {
        path: 'three',
        component: ThreeComponent,
        resolve: {products: ProductService}
      }
    

    从其他页面跳转到three页面

    <a [routerLink]="['three']">three</a>
    

    ThreeComponent 页面拿到这个值

    export class ThreeComponent implements OnInit {
    
      constructor(private route:ActivatedRoute) { }
      ngOnInit(): void {
        // 拿到获取的数据
        console.log(this.route.snapshot.data['products']);
      }
    }
    

    rxjs 中的map和switchMap区别

    switchMap 创建一个内部课观察对象,进行订阅并发出其值为可观察者

    of(1, 2, 3, 4).pipe(
          map(v => v * 2),
          toArray()
        ).subscribe(res=>{
          console.log(res);
         //[2, 4, 6, 8]
        })
    
    of(1, 2, 3, 4, 5).pipe(
          switchMap(val => of(val * 2)),
          toArray()
        ).subscribe(res=>{
          console.log(res);
          //  [2, 4, 6, 8, 10]  
        })
    

    点击按钮,每1s发送一个值,再次点击,取消之前的订阅重新开始发送值

    <button #button>click</button>
    
    @ViewChild('button') button;
      ngAfterViewInit(): void {
        fromEvent(this.button.nativeElement,'click').pipe(
          switchMap(()=>interval(1000))
        ).subscribe(res=>{
          console.log(res);
        })
      }
    

    比如拿到xxx/:id

    this.activateRoute.paramMap.pipe(
    	switchMap(params=>params.get('id'))
    ).subscribe(res=>{
        console.log(id)
    })
    

    from表单触发某个值,提交请求

    this.mainForm.get("productCode").valueChanges
    .pipe(
      debounceTime(700),
      switchMap(val => {
        return this.queryDepositData();
      })
    )
    .subscribe(data => {
      this.product=data;
    })
    

    Rxjs 学习原理图

    https://thinkrx.io/rxjs/

    看着原理图学习,会印象深刻一些

    angular的相关命令细节

    --flat 强制修改创建文件的位置

    ng g c --f  fix/hello
    在app的fix/hello位置下创建一个hello组件
    

    -export 添加到对应模块的exports

    ng  g c  home --export
    // 会添加到对应模块的exports
    

    --prefix 添加组件选择器前缀

    ng g c --p=d  hello
    // 选择器的名称  d-hello
    
    selector: 'd-hello',
    

    --selector 替换组件选择器

    ng g c fix/hello-e --selector=hello-g
    
      selector: 'hello-g',// 而不是hello-e
    

    创建一个class 文件

    ng g class xxx
    

    创建模块

    ng g m south    //会创建一个south模块
    ng g m south --routing // 同时创建模块和路由
    如果创建了模块没有没有创建路由,可以使用下面的命令
    ng g m -f south --routing
    

    模板字符串规范

    不好

    {{num/60}}
    

    推荐

    {{num}}
    
    get num(){
        return this.total/60
    }
    

    父子组件传递

    不好

    {{getOffer(amount)}}
    
    @Input() amount:number
    
    getOffer(amount:number){
        if(amount > 3500  && amount < 4999)
           return `You will get 20% off on 5k purchase`;
        else if (amount > 5000)
           return `You will get 30% off on 7k purchase`;
        else
           return `5% off on your existing purchase.`;
    }
    

    推荐

    {{offerMessage}}
    
    offerMessage: string;
    
    @Input() set amount(value: number) {
        let message: string = '';
        if (value > 5000)
            message = `You will get 30% off on 7k purchase`;
        else if (value > 3500 && value < 4999)
            message = `You will get 20% off on 5k purchase`;
        else
            message = `5% off on your existing purchase.`;
        this.offerMessage = message;
    }
    

    正常情况下这样也行

    {{getGrade(student)}}
    
    getGrade(marks: number) {
        let grade: string = 'F';
        if (marks >= 85)
            grade = 'S'
        else if (marks > 60 && marks < 85)
            grade = 'A'
        return grade;
    }
    

    在使用ngFor 绑定数据的时候

    <tr *ngFor="let student of students; trackBy:trackByFn">
        <td>{{student.name}}</td>
        <td>{{student.grade}}</td>
    </tr>
    
    trackByFn(index, item) {
        return item.id;
    }
    

    RXjs 具体api的实际运用

    debounceTime

    输入数据搜索资料的时候,而不按搜索的数据按钮,请求下拉框

    我们发现当修改一个的时候回立刻请求值,所以我们可以加上,在一段时间内,修改只会发一次请求

    this.from.get('xxx').valueChanges.pipe(
    	debounceTime(300),
        switchMap(key=>this.http.get('xxx',key))
    )
    

    distinctUntilChanged

    当当前值和之前值有变化才会发送订阅

    <form [formGroup]="myForm">
      <input formControlName="firstName">
    </form>
    
     constructor(private fb: FormBuilder,) {
      }
    
     myForm = this.fb.group({
          firstName: ['']
        }
      );
    
    ngOnInit(): void {
        this.myForm.get('firstName').valueChanges.pipe(
          debounceTime(300),// 当300ms没有新资料,才会运行
          distinctUntilChanged()// 当[内容真正有修改]时,才运行搜索
        ).subscribe(res=>{
          console.log(res);
        })
      }
    

    filter

     this.myForm.get('firstName').valueChanges.pipe(
          debounceTime(300),// 当300ms没有新资料,才会运行
          distinctUntilChanged(),// 当[内容真正有修改]时,才运行搜索
          filter(key =>key.length>4)// 当之大于4的是偶,才会进行搜索
        ).subscribe(res => {
          console.log(res);
        });
    

    完整版

     public todos;
      ngOnInit(): void {
        this.todos= this.myForm.get('firstName').valueChanges.pipe(
          map((query: string) => query ? query.trim() : ''),
          filter(v => v.length > 3),
          debounceTime(300),
          distinctUntilChanged(),// 内容有修改
          switchMap(query => of('111' + query)), //模拟发请求
          shareReplay(1)// 避免重复载入
        );
      }
    

    Subject

      public sub = new Subject();
    	sub.subscribe(res=>{
          console.log(res); //2,3,5,6
        })
    	this.sub.next(2);
        this.sub.next(3);
    	this.sub.subscribe(res=>{
          console.log(res); //5,6
        })
        this.sub.next(5)
        this.sub.next(6)
    

    ReplaySubject

    // 指定记录次数  	
    public subject = new ReplaySubject(2);
    	ngOnInit(): void {
            this.subject.next(1);
            this.subject.subscribe(res=>{
              console.log(res); //1,2,3,4
            })
            this.subject.next(2)
            this.subject.next(3)
            this.subject.subscribe(res=>{
              console.log(res);//2,3,4 (2,3是最近2次重播的值)
            })
            this.subject.next(4)
    	}	
    

    asyncSubject

    只有在complete() 才会被呼叫,订阅到[最后一次next()]的内容

      public asySub = new AsyncSubject();
      ngOnInit(): void {
        this.asySub.subscribe(res=>{
          console.log(res); //3
        })
        this.asySub.next(1)
        this.asySub.next(2)
        this.asySub.next(3)
        this.asySub.complete()
      }
    

    处理错误

    subject.subscribe(
    res=>{
    // 成功    
    },error=>{
    // 失败    
    })
    

    修改,记录错误类似于try...catch

    this.http.get('....').pipe(
    	catchError(err=>{
            console.log(err)
            return of([])
        })
    )
    模拟
     throwError('xxx').pipe(
          catchError(err=>of(1))
        ).subscribe(res=>{
          console.log(res);//1
        })
    of(throwError('xxx')) 如果这样是就是of()了一个流,所以的是一个流,应该是上面的那种写法
    

    如果想主动抛出错误

    this.http.get('....').pipe(
        tap(data=>{  //但是你要记得 tap 是不会影响流的
            if(data.length==0){
                throwError('no data')
            }
        }),
    	catchError(err=>{
            console.log(err)
            return of([])
        })
    )
    

    finalize 放置到最后执行的程式,这样this.lading=false 就不用subscribe里面了

    this.http.get('...').subscribe(res=>{
        this.loading=false;
    },error=>{
        this.loading=false;
    })
    修改
    this.http.get('...').pipe(
    	finalize(()=>{
            // 不管出现什么错误等等等,都一定会进入finalize里面
            this.loading=false
        })
    )
    

  • 相关阅读:
    Java核心技术(初阶)知识点复习——[2]面向对象思想
    Java核心技术(初阶)知识点复习——[1]Java的类结构和main函数
    printStream与printWriter
    java反射的初步探索
    JDKJREJVM的关系
    树链剖分模板
    树状数组模板2
    树状数组模板1
    树状数组+欧拉降幂
    线段树模板二
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/13292780.html
Copyright © 2020-2023  润新知