angular9 学习进阶(十六)

rxjs 实用

map

讲一个阵列转成另外一个阵列

 of(1).pipe(
      map(v => v * 20)
    ).subscribe(res => {
      console.log(res); // 20
    });

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

tap

不会帮助我们进行资料转化,不会影响rxjs资料流,不会都程序有什么影响

of('xxx').pipe(
      tap(v=>console.log)
    )

shareReplay 避免重新载入

我们会发生shareReplay(1)只发了一次请求

public todos;

  ngOnInit(): void {
    this.todos = this.http.get('https://jsonplaceholder.typicode.com/todos/').pipe(
      shareReplay(1)
    );
  }

  add() {// 点击的时候执行这个函数
    this.todos.subscribe(res => {
      console.log(res);
    });
  }

Subscription(相当于取消订阅)

someSubscriptions = new Subscription();
 
ngOnInit() {
  this.someSubscriptions.add(xx$.subscribe(...));
  this.someSubscriptions.add(yy$.subscribe(...));
}
 
ngOnDestroy() {
  this.someSubscriptions.unsubscribe();
}

禁止使用返回键

网上的

    history.pushState(null, null, document.URL);
    window.addEventListener('popstate', function () {
      history.pushState(null, null, document.URL);
    });

实现:不能我们使用路由监听,然后调用history.pushState 方法,改变网址就不会跳转

 this.router.events.subscribe((event: any) => {
      if (event instanceof NavigationEnd) {
        history.pushState(null, null, document.URL);
      }
});

angular 动画

https://indepth.dev/in-depth-guide-into-animations-in-angular/

style在js中的命名约束

驼峰式,或者破折号

style({
    backgroundColor:'green'
})

style({
    "background-color":"green"
})

执行顺序

:enter 状态更改将ngOnInit周期之后调用

:leave 状态更改讲ngOnDestroy 周期调用后,立即执行

设置

import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports: [
    BrowserAnimationsModule
  ],
})

动画声明

*    通配符就是默认状态或者所有状态
void  dom删除元素
自定义   特定的状态

状态变化之间的转化

import { trigger, state, style, animate, transition } from '@angular/animations';

@Component({
  ...
  animations: [
    trigger('enabledStateChange', [
      state(
        'default',
        style({
			opacity: 1,
		})
	),
	state(
		'disabled',
		style({
			opacity: 0.5,
        })
      ),
      transition('* => *', animate('300ms ease-out')),
    ])
  ]
})

trigger

  • 接受动画接触器的名称+转换方法的数组配置

state

  • 接受状态名称以及处于指定状态时应有的样式

style

  • css样式

transition

  • 指定在不同状态一起方向之间转化的配置
  • animate 动画的属性

例子

<button (click)="clickBool()">点我</button>
<div @fadeSlideInOut *ngIf="bool"  class="aaa"  >
  <p>1我是一个好人</p>
  <p>2我是一个好人</p>
  <p>3我是一个好人</p>
  <p>4我是一个好人</p>
  <p>5我是一个好人</p>
  <p>6我是一个好人</p>
  <p>7我是一个好人</p>
  <p>8我是一个好人</p>
  <p>9我是一个好人</p>
  <p>10我是一个好人</p>
</div>

ts
  public bool:boolean=false;
  clickBool():void{
    this.bool=!this.bool
  }

@Component({
	...
  animations: [
      
    trigger('fadeSlideInOut',[
      transition(':enter', [
        style({ opacity: 0, transform: 'translateY(10px)' }),
        animate('500ms', style({ opacity: 1, transform: 'translateY(0)' })),
      ]),
      transition(':leave', [
        animate('500ms', style({ opacity: 0, transform: 'translateY(10px)' })),
      ]),
    ])
  ]
})
下面这种模式是从一个状态到另一种状态
 trigger('enabledState', [
      state(
        'default',
        style({
          opacity: 1,
        })
      ),
      state(
        'disabled',
        style({
          opacity: 0.5,
        })
      ),
      transition('* => *',animate('300ms ease-out'))
    ]),

MergeMap

MergeMap 本质上是mergeAll 和 map 的结合

 getData(param){
    return of(`retrieved new data with param ${param}`).pipe(
      delay(1000)
    )
  }

ngOnInit(): void {
    from([1, 2, 3, 4]).pipe(
      map(val=>this.getData(val)),
      mergeAll()
    ).subscribe(res=>{
      console.log(res);
    })
  }
  
修改
from([1, 2, 3, 4]).pipe(
      mergeMap(value => of(`retrieved new data with param ${value}`).pipe(delay(1000)))
    ).subscribe(res=>{
      console.log(res);
    })

concatMap

from([1, 2, 3, 4]).pipe(
      concatMap(value => of(`retrieved new data with param ${value}`).pipe(delay(1000)))
    ).subscribe(res=>{
      console.log(res);
    })

两者的区别

concatMap 等待,按顺序执行任务

mergeMap 不等待,并发执行任务

延迟加载

https://stackblitz.com/edit/lazyload-images-matew17?file=src%2Fapp%2Fapp.component.html

确定分配断言

let num!:string;
!这个是告诉语法提示工具,这个已经赋值了,不需要你来判断

点击编辑文本

参考资料

第一种方法

子组件

import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Observable} from 'rxjs';
import {State} from '../reducer/scoreboard/scoreboard.reducer';
import {select, Store} from '@ngrx/store';

@Component({
  selector: 'app-hello-one',
  templateUrl: './hello-one.component.html',
  styleUrls: ['./hello-one.component.less']
})
export class HelloOneComponent implements OnInit {
  public isEditing: boolean = false;
  public pendingValue: string = '';
  @Input('value') value!: string;
  @Output('valueChange') valueChangeEvents: EventEmitter<string> = new EventEmitter();
  constructor() {
  }
  public cancel(): void {
    this.isEditing = false;
  }
  // 启动对值得编辑.
  public edit(): void {
    this.pendingValue = this.value;
    this.isEditing = true;
  }
  public processChanges(): void {
    // 当值改变的时候才执行
    if (this.pendingValue !== this.value) {
      this.valueChangeEvents.emit(this.pendingValue);
    }
    this.isEditing = false;
  }
  ngOnInit(): void {
  }
}
<div *ngIf="isEditing">
  <input type="text"
         name="value"
         [(ngModel)]="pendingValue"
		autofocus
         (keydown.Enter)="processChanges()"
         (keydown.Escape)="cancel()"
  >

  <button (click)="processChanges()">
    Save
  </button>
  <a
    (click)="cancel()"
    (keydown.Enter)="cancel()"
    tabindex="0">
    Cancel
  </a>
</div>
<div *ngIf="( ! isEditing )" (click)="edit()">
  {{ value }}
</div>

父组件

 <li *ngFor="let project of projects">
    <app-hello-one [value]="project.name" (valueChange)="saveProject(project,$event)"></app-hello-one>
  </li>

    export interface Project {
      id: string;
      name: string;
    }

     saveProject(project: Project, newName: string) {
        project.name=newName
      }

 public projects: Project[] = [
    { id: "p1", name: "My Groovy Project" },
    { id: "p2", name: "Another Cool Project" },
    { id: "p3", name: "Much Project, Such Wow" },
    { id: "p4", name: "A Good Project" }
  ];

第二种

巧妙的运行了浅拷贝,仔细思考了半小时才明白

<ul>
  <li
    *ngFor="let item of arr"
    [ngSwitch]="(item===smg)">
    <div *ngSwitchCase="true">
      <label>
        <input type="text"
        [(ngModel)]="pendingValue"
         autofocus
         (keydown.enter)="processChange()"
        >
      </label>
      <button (click)="processChange()">Save</button>
      <a (click)="cancel()">Cancel</a>
    </div>
    <div *ngSwitchCase="false" (click)="edit(item)">
      {{item.name}}
    </div>
  </li>
</ul>
import {Component, Input, OnInit, Output, EventEmitter} from '@angular/core';

interface ArrayId {
  id: number;
  name: string
}

@Component({
  selector: 'app-hello-tow',
  templateUrl: './hello-tow.component.html',
  styleUrls: ['./hello-tow.component.less']
})
export class HelloTowComponent implements OnInit {
  public pendingValue: string = '';
  public smg: ArrayId | null;
  public arr: ArrayId[] = [
    {id: 1, name: 'xxxxxx'},
    {id: 2, name: 'dddd'},
    {id: 3, name: 'ccc'},
    {id: 4, name: 'bbb'},
  ];

  processChange() {
    if (this.pendingValue !== this.smg!.name) {
      // 浅拷贝,终于看懂了,我的天,这块代码巧妙的运用的浅拷贝的方法进行修改
      this.smg!.name = this.pendingValue;
    }
    this.smg = null;
  }

  constructor() {
  }

  ngOnInit(): void {
  }


  edit(item: ArrayId): void {
    this.pendingValue = item.name;
    this.smg = item;
  }

  cancel(): void {
    this.smg = null;
  }
}
posted @ 2020-07-27 18:26  猫神甜辣酱  阅读(598)  评论(0编辑  收藏  举报