angular11学习(十八)

angular img 404的问题

必须放在src/assets

请使用相对路径

Form 查找后台的

以前

fg.controls['name']
fg.controls['address'].controls['city']

现在

fg.get('address.city')
fg.get(['address', 'street'])

禁用

fg.controls['name'].disable();
fg.controls['city'].disable({ onlySelf: true }); // 不更新父级

解除 enabled

Form 输入字母转大写

NgModel

<input type="text" [(ngModel)]="num" appMyDirective>


import {Directive, HostListener} from '@angular/core';
import {NgModel} from '@angular/forms';

@Directive({
  selector: '[appMyDirective]'
})
export class MyDirectiveDirective {
  constructor(private model: NgModel) {

  }

  @HostListener('input', ['$event.target'])
  ngModelChanges(e) {
    let a=e.value.toUpperCase()
    // 写入
    this.model.valueAccessor.writeValue(a)
    // 更新
    this.model.viewToModelUpdate(a)
  }

}

formControlName

<form  [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <label>
    firstName: <input type="text" formControlName="firstName">
  </label>
  <label>
    lastName: <input type="text" formControlName="lastName">
  </label>
  <div formGroupName="address">
    <label>
      address1: <input type="text" formControlName="address1">
    </label>
    <label>
      address2: <input type="text" formControlName="address2" >
    </label>
  </div>
</form>
 public myForm: FormGroup;
  public str:string;

  constructor( private fb: FormBuilder) {
    this.myForm = this.fb.group({
      firstName: [''],
      lastName: [''],
      address: this.fb.group({
        address1: [''],
        address2: [''],
      })
    });
    this.myForm.valueChanges.subscribe(e => {
      if(this.str!==this.myForm.get('firstName').value){
        this.myForm.get('firstName').setValue(e.firstName.toUpperCase(),{onlySelf:true})
      }
      this.str=this.myForm.get('firstName').value;
    });
  }

升级版本

  <label>
      address2: <input type="text" formControlName="address2" appMyDirective>
    </label>

export class MyDirectiveDirective {
  constructor(private injector: Injector) { }

  @HostListener('input', ['$event.target'])
  ngModelChanges(e) {
    let a = e.value.toUpperCase();
    // 这个代码好牛逼,拿到注射器实例
    let {control} = this.injector.get(NgControl);
    control.setValue(a)
    // 更新规则
    control.updateValueAndValidity();
  }
}

注册器的相关使用

新建一个服务

import {Injectable} from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class HelloService {

  constructor() {
  }

  say(from: string) {
    console.log(`hello ${from}`);
    return true;
  }
}

组件中直接查找使用

 ngAfterViewInit() {
    const service=inject(HelloService)
    service.say('AppModule')
  }

服务的使用

useClass

告诉我们使用了那个类

import {Injectable} from '@angular/core';

@Injectable({
  providedIn: 'root',
  useClass:HelloService
})
export class HelloService {

  constructor() {
  }

  say(from: string) {
    console.log(`hello ${from}`);
    return true;
  }
}

进行使用
  constructor(private helloService:HelloService) {
    this.helloService.say('bbbb')
  }

创建库

ng g  library  my-lib

projects 里面有个 my-lib 项目文件夹

package.json

    "ng-packagr": "^10.0.0",

app.module

import {MyLibModule} from '../../projects/my-lib/src/lib/my-lib.module'

@NgModule({
    imports: [
            MyLibModule
    ]
})

页面的使用

<lib-my-lib></lib-my-lib>

主模块子模块关于NavigationEnd 问题

同事今天遇到一个问题主模块app.componentRouter.event 事件无法检测某个模块的NavigationEnd 事件

最终通过跟同事一起分析的解决思路是

主模块应该把 router.event 放在 constructor 
而子模块的东西应该放在生命周期里面`ngOnInit`

发现一个有趣的问题

如果判断clickdrag 事件

 let a=document.querySelector('#aaa');
    merge(
      fromEvent(a,'mousedown').pipe(mapTo(1)),
      fromEvent(a,'mousemove').pipe(mapTo(2)),
    ).pipe(
      sample(fromEvent(a,'mouseup'))// 促发条件:松开鼠标促发
    ).subscribe(flag=>{
      if (flag == 1) {
        console.log('click');
      }else if (flag == 2) {
        console.log('drag');
      }
    })

双向数据绑定css变量

<input type="number" [(ngModel)]="x">
<p [style.--num]="x">hello world</p>

p{
  font-size:calc(var(--num)*1px)
}

x = 20;

我们发现 x=20 变量了css变量进行操作

自定义指令

<div appChColor>
  hello world
</div>

@Directive({
  selector: '[appChColor]'
})
export class ChColorDirective {

  constructor(
    private el: ElementRef,
    private renderer: Renderer2
  ) {
    this.changeColor('red')
  }

  changeColor(color: string) {
    this.renderer.setStyle(this.el.nativeElement, 'color', color)
  }
  // click 的时候修改颜色
  @HostListener('click')
  foo(){
    this.changeColor('green')
  }
}

Rxjs 错误处理

  this.http.get('/assets/data.json--').pipe(
      catchError(error=>of([]))
    ).subscribe(res=>{
      console.log(res);
    })
  • 我们正在向catchError运算符传递一个函数,这是错误处理函数
  • 错误处理函数不会立即被调用,通常,通常不会被调用
type TypeArrays = {
  data: Array<any>
}

export class UserComponent implements OnInit {

  constructor() {}

  loading: boolean;
  arr: Array<any>

  ngOnInit(): void {
    this.http.get<TypeArrays>('/assets/data.json').pipe(
      finalize(() => {
        this.loading = !!this.arr.length;
      })
    ).subscribe(res => {
      this.arr = res.data;
    })
  }

}

angular 不变形的重要性

<app-dev-card-v1 class="card" *ngFor="let dev of devs" [dev]="dev">
</app-dev-card-v1>

ngOnChanges生命周期检测值发生变化

set 输入属性,ngOnChanges生命周期挂钩的替代方法,并在传递新值时执行

@Input() 
set dev(val: Dev) {
    this._dev = val;
    this.seniorityLevel = this.getSeniorityLevel();
  }

如果您不能轻松地切换到不变的更新模式,则解决陈旧数据呈现问题的一种方法是使用getter即时计算视图模型数据

export class DevCardV5Component {
  @Input() public dev: Dev;

  public get seniorityLevel(): SeniorityLevel {
    console.log("seniorityLevel getter called");

    return this.getSeniorityLevel();
  }

  private get skill(): number {
    return this.dev.skill;
  }
}

但是,您仍然不能使用该组件的OnPush更改检测策略。而且,在每个更改检测周期都将调用getter

另一种选择是在ngDoCheck生命周期挂钩中执行计算,它被认为是不得已的方法,因为与getter相似,它在每个变更检测周期内都会被调用

  ngDoCheck() {
    this.seniorityLevel = this.getSeniorityLevel();
  }
posted @ 2020-12-15 01:04  猫神甜辣酱  阅读(756)  评论(0编辑  收藏  举报