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();
  }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM