5 tips untuk meningkatkan keterampilan Angular Anda

Musim panas ini, Roma dan saya meluncurkan serangkaian tweet dengan tip dan trik Angular yang bermanfaat. Inisiatif ini disambut hangat oleh masyarakat dan saya memutuskan untuk menulis artikel ringkasan. Berikut adalah 5 rekomendasi saya untuk dibagikan dengan pengembang. Tips ini akan didukung oleh contoh spesifik dari twitter saya . Mereka akan membantu Anda meningkatkan keterampilan Anda, atau setidaknya memberi Anda beberapa tip praktis.

1. Pahami mekanisme pemeriksaan perubahan

Ada banyak artikel mendalam yang bagus di internet tentang memeriksa perubahan di Angular. Misalnya yang ini. Jadi mari kita memoles dasar-dasarnya dan mendapatkan tipnya.

Dasar

Angular : Default OnPush. tick . Zone.js, . view , .

Default vs OnPush

, Default. , , OnPush. . , OnPush .

@HostListener Angular OnPush. , RxJS? ChangeDetectorRef markForCheck(), . async , . . 

:

<div *ngIf="stream$ | async as result">
    β€¦
</div>

, falsy-? ngIf . , :

@Directive({
  selector: "[ngLet]"
})
export class LetDirective<T> {
  @Input()
  ngLet: T;

  constructor(
    @Inject(ViewContainerRef) container: ViewContainerRef,
    @Inject(TemplateRef) templateRef: TemplateRef<LetContext<T>>
  ) {
    container.createEmbeddedView(templateRef, new LetContext<T>(this));
  }
}

NgZone

OnPush, . NgZone .runOutsideAngular(). . Default . , mousemove scroll. RxJS- : β€” , β€” , :

class ZonefreeOperator<T> implements Operator<T, T> {
  constructor(private readonly zone: NgZone) {}

  call(observer: Observer<T>, source: Observable<T>): TeardownLogic {
    return this.zone.runOutsideAngular(
      () => source.subscribe(observer)
    );
  }
}

export function zonefull<T>(zone: NgZone): MonoTypeOperatorFunction<T> {
  return map(value => zone.run(() => value));
}

export function zonefree<T>(zone: NgZone): MonoTypeOperatorFunction<T> {
  return source => source.lift(new ZonefreeOperator(zone));
}

, @HostListener, β€” EventManagerPlugin. open-source- ng-event-plugins. . .

2. RxJS

RxJS β€” . , . , β€” 

β€” . , , :

, , . CSS RxJS:

@Directive({
  selector: "[sticky]",
  providers: [DestroyService]
})
export class StickyDirective {
  constructor(
    @Inject(DestroyService) destroy$: Observable<void>,
    @Inject(WINDOW) windowRef: Window,
    renderer: Renderer2,
    { nativeElement }: ElementRef<HTMLElement>
  ) {
    fromEvent(windowRef, "scroll")
      .pipe(
        map(() => windowRef.scrollY),
        pairwise(),
        map(([prev, next]) => next < THRESHOLD || prev > next),
        distinctUntilChanged(),
        startWith(true),
        takeUntil(destroy$)
      )
      .subscribe(stuck => {
        renderer.setAttribute(
          nativeElement, 
          "data-stuck", 
          String(stuck)
        );
      });
  }
}

RxJS Angular- . RxJS , . , , .

, . , RxJS, β€” . - . ( ).

3. TypeScript

Angular- TypeScript. , , . strict: true. . cannot read property of null undefined is not a function.

TypeScript β€” , , , . , API. . RxJS- fromEvent:

//     currentTarget
export type EventWith<
  E extends Event,
  T extends FromEventTarget<E>
> = E & {
  readonly currentTarget: T;
};

//   fromEvent
export function typedFromEvent<
  E extends keyof GlobalEventHandlersEventMap,
  T extends FromEventTarget<EventWith<GlobalEventHandlersEventMap[E], T>>
>(
  target: T,
  event: E,
  options: AddEventListenerOptions = {},
): Observable<EventWith<GlobalEventHandlersEventMap[E], T>> {
  return fromEvent(target, event, options);
}

, , currentTarget β€” , .

API, , , . , .

TypeScript. , . : any. , unknown.

TypeScript, . . , , , : , , β€” number. TypeScript , runtime :

export function assert<T, K extends keyof T>(
  assertion: (input: T[K]) => boolean,
  messsage: string
): PropertyDecorator {
  return (target, key) => {
    Object.defineProperty(target, key, {
      set(this: T, initialValue: T[K]) {
        let currentValue = initialValue;

        Object.defineProperty(this, key, {
          get(): T[K] {
            return currentValue;
          },
          set(this: T, value: T[K]) {
            console.assert(assertion(value), messsage);
            currentValue = value;
          }
        });
      }
    });
  };
}

, super()? Angular , :

β€” . Web Audio API Angular, . .

4. Dependency Injection.

DI β€” , Angular . , . .

, DI, .

RxJS

, RxJS. , , , . Angular :

@Injectable()
export class DestroyService extends Subject<void> implements OnDestroy {
    ngOnDestroy() {
        this.next();
        this.complete();
    }
}

DI. requestAnimationFrame . . , :

DI β€” . window navigator β€” Angular Universal . , . . . WINDOW DOCUMENT:

export const WINDOW = new InjectionToken<Window>(
  'An abstraction over global window object',
  {
    factory: () => {
      const {defaultView} = inject(DOCUMENT);

      if (!defaultView) {
        throw new Error('Window is not available');
      }

      return defaultView;
    },
  },
);

, open-source-, . Angular Universal - . , , - .

. DI . .

5. ,

Angular . . . : . , , .

β€” Β« Β»? ngOnChanges . -, , , - . 

β€” . - , .

β€” , . . , . , β€” , .

, , .

Template reference variables

Angular @ViewChild. , :

<input #input>
<button (click)="onClick(input)">Focus</button>

template reference variable , . .

, DOM-, ? @ViewChild(MyComponent, {read: ElementRef}), , exportAs:

@Directive({
    selector: '[element]',
    exportAs: 'elementRef',
})
export class ElementDirective<T extends Element> extends ElementRef<T> {
    constructor(@Inject(ElementRef) {nativeElement}: ElementRef<T>) {
        super(nativeElement);
    }
}

ComponentFactoryResolver . , ngComponentOutlet? . β€” , Dependency Injection. ngComponentOutlet Injector, .

, , . . .

, . open-source- ng-polymorpheus. , , ngTemplateOutlet, ngContentOutlet . , ! .

. , . !




All Articles