angular大寫指令,繼承, 防止XSS攻擊, 沒有ngOnInit的組件初始化

rxjs

const nums = of(1, 2, 3);

const value = map((val: number) => val * val);
const valueNum = value(nums);
valueNum.subscribe((v) => console.log(v));

指令

@HostBinding('attr.data-xxx')
@Input() type:'aaa'|'bbb'|'ccc'='ccc'

angular 修改路徑

tsconfig.json

"compilerOptions": { 
  ..... 
  "paths": { 
    "@domain": ["./src/app/domain/*"] 
    "@repo": ["./src/app/repository/*" ] 
  } 
}

使用可以直接從路徑在找

import { GENERIC_DATA, IGenericData } from '@domain';
import { GenericDataRepository } from '@repo';

繼承調用繼承的生命週期

export class OneExtendsComponent implements OnInit {

    constructor() {
    }

    ngOnInit(): void {
        console.log('測試進行了嗎');
    }

    add() {
        console.log(1);
    }
}

export class OneComponent extends OneExtendsComponent implements OnInit {

    constructor() {
        super();
    }

    ngOnInit(): void {
        this.add();
        // 可以使用super關鍵字來引用基類實例並在被覆蓋的方法中調用原始方法
        super.ngOnInit();
    }

}

大寫指令

@Directive({
    selector: '[toUppercase]',
    providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => ToUppercaseDirective),
        multi: true
    }]
})
export class ToUppercaseDirective implements ControlValueAccessor {
    private onChange: (val: string) => void;
    private onTouched: () => void;

    constructor(
        private elementRef: ElementRef,
        private renderer: Renderer2
    ) {
    }

    @HostListener('input', ['$event.target.value'])
    onInputChange(value: string) {
        value = value.toUpperCase()
        this.updateTextInput(value);
        this.onChange(value);
    }

    @HostListener('blur')
    onBlur() {
        this.onTouched();
    }

    private updateTextInput(value: string) {
        this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
    }

    // ControlValueAccessor Interface
    registerOnChange(fn: any): void {
        this.onChange = fn;
    }

    registerOnTouched(fn: any): void {
        this.onTouched = fn;
    }

    setDisabledState(isDisabled: boolean): void {
        this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', isDisabled);
    }

    writeValue(value: any): void {
        if (value == null) {
            value = ''
        }
        this.updateTextInput(value);
    }
}

防止XSS 攻擊

<textarea [(ngModel)]="str" (ngModelChange)="changeModel($event)"></textarea>
<div [innerHTML]="strHtml"></div>
export class OneComponent implements OnInit {
    str = '';
    strHtml = '';
    constructor(@Inject(DomSanitizer) private readonly sanitizer: DomSanitizer) { }

    ngOnInit(): void { }

    public changeModel($event: any): void {
        this.unwrap($event);
    }

    unwrap(value: SafeValue | null): void {
        this.strHtml = this.sanitizer.sanitize(SecurityContext.HTML, value) || '';
    }
}

!:或者?:

!:  等下賦值
?:  可能會賦值,所以可能會爲undefined

沒有 ngOnInit 的組件初始化的使用

傳統

data: MyData;

constructor(private readonly dataService: DataService) { }

ngOnInit() {
  this.dataService.getData().subscribe(
    data => this.data = data,
  );
}

修改後

readonly data$ = this.dataService.getData().pipe(
  map((response) => {
    const first = response.data[0];
    
    return {
      name: response.name,
      time: new Date(response.time)
    }
  }),
);

constructor(private readonly dataService: DataService) { }

使用

<p> {{ (data$ | async).name }} </p>

重構嵌套流

傳統

hero?: { name: string };

constructor(
  private readonly route: ActivatedRoute,
  private readonly heroService: HeroService,
) { }

ngOnInit() {
  this.route.params.subscribe(
    (params) = > {
      const id = params.id;

      this.heroService.getHero(id).subscribe(
        response => this.hero = response
      );
    }
  )	
}

修改

<>
readonly hero$ = this.route.params.pipe(
  switchMap(params => this.heroService.getHero(params.id))
);

constructor(
  private readonly route: ActivatedRoute,
  private readonly heroService: HeroService,
) { }

Input拿到值的用法

傳統

export class NameComponent implements OnInit {
  @Input() name: string;
  @Input() surname: string;

  fullName: string;

  ngOnInit() {
    this.fullName = `${this.name} ${this.surname}`;
  }
}

爲了防止值的變更, 我們應該使用 ngOnChanges

export class NameComponent implements OnChanges {
  @Input() name: string;
  @Input() surname: string;

  fullName: string;

  ngOnChanges() {
    this.fullName = `${this.name} ${this.surname}`;
  }
}

我們應該使用

export class NameComponent {
  @Input() name: string;
  @Input() surname: string;

  get fullName(): string {
    return `${this.name} ${this.surname}`
  }
}

或者使用

interface MyDTO {
  data: {
    name: string;
    time: string;
  }[]
}
export class TimeComponent {
  @Input() 
  set vm(value: MyDTO) {
    const first = value.data[0];
   
    this.time = new Date(first.time);
  }

  time: Date;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章