라이브러리를 Angular 지시문으로 래핑

이것은 여러 프레임워크에서 사용할 유연한 JS 라이브러리 설계에 대한 시리즈의 두 번째 기사입니다.

시리즈의 첫 번째 기사에서는 브라우저에서 스와이프 감지를 위한 바닐라 TS/JS 라이브러리를 구축했습니다. 널리 사용되는 모든 JS 프레임워크로 빌드된 애플리케이션에서 그대로 사용할 수 있지만, 우리는 조금 더 나아가 여러분이 선택한 프레임워크에서 사용될 때 우리 라이브러리를 일류 시민으로 만들고 싶습니다.

이 기사에서는 스 와이프 감지 라이브러리를 Angular 지시문으로 래핑합니다.

💡 이 기사는 내부적으로 사용되는 스와이프 감지 라이브러리의 공개 인터페이스에 대해 잘 알고 있음을 암시합니다. 시리즈의 첫 번째 기사를 읽지 않았다면 이 기사의 내용을 따라가는 것만으로도 충분할 것입니다.

작동 방식



Angular 구성 요소의 요소에서 스와이프를 감지해야 하는 경우 대상 요소에 전용 속성 지시문을 첨부하는 것만큼 쉬워야 합니다.

  <div ngSwipe (swipeEnd)="onSwipeEnd($event)">Swipe me!</div>


여기서는 DOM을 조작하지 않을 것이므로 Anattribute directive이면 충분합니다.

호스트 요소에 액세스하기



스 와이프 구독이 기대하는 것을 기억해 봅시다. 기본 라이브러리의 공용 인터페이스에 따라 다음 구성을 제공해야 합니다.

export function createSwipeSubscription({
    domElement,
    onSwipeMove,
    onSwipeEnd
  }: SwipeSubscriptionConfig): Subscription {
// ...
}


따라서 지시문이 연결된 호스트 요소에 대한 액세스 권한을 얻어 createSwipeSubscription 함수에 전달해야 합니다. 이것은 Angular 구성 요소에 대한 간단한 유형의 작업입니다.

constructor(
  private elementRef: ElementRef
) {}


삽입된nativeElementelementRef 속성은 기본 네이티브 DOM 요소에 대한 참조를 보유합니다. 따라서 스와이프 구독을 생성할 때 이 참조를 사용하여 대상 DOM 요소를 전달할 수 있습니다.

this.swipeSubscription = createSwipeSubscription({
  domElement: this.elementRef.nativeElement,
  //..
});


완벽한 솔루션



지시문 코드의 나머지 부분은 매우 간단합니다. 다음은 완전한 솔루션입니다.

import { Directive, ElementRef, EventEmitter, NgZone, OnDestroy, OnInit, Output } from '@angular/core';
import { Subscription } from 'rxjs';
import { createSwipeSubscription, SwipeEvent } from 'ag-swipe-core';

@Directive({
  selector: '[ngSwipe]'
})
export class SwipeDirective implements OnInit, OnDestroy {
  private swipeSubscription: Subscription | undefined;

  @Output() swipeMove: EventEmitter<SwipeEvent> = new EventEmitter<SwipeEvent>();
  @Output() swipeEnd: EventEmitter<SwipeEvent> = new EventEmitter<SwipeEvent>();

  constructor(
    private elementRef: ElementRef,
    private zone: NgZone
  ) {}

  ngOnInit() {
    this.zone.runOutsideAngular(() => {
      this.swipeSubscription = createSwipeSubscription({
        domElement: this.elementRef.nativeElement,
        onSwipeMove: (swipeMoveEvent: SwipeEvent) => this.swipeMove.emit(swipeMoveEvent),
        onSwipeEnd: (swipeEndEvent: SwipeEvent) => this.swipeEnd.emit(swipeEndEvent)
      });
    });
  }

  ngOnDestroy() {
    this.swipeSubscription?.unsubscribe?.();
  }
}


지시문은 다음과 같은 간단한 루틴을 수행합니다.
  • 기본 DOM 요소의 참조를 가져옵니다.
  • 디렉티브의 onSwipeMove로 내보내는 onSwipeEndOutput 이벤트 핸들러를 사용하여 스와이프 구독을 생성합니다.
    관련 이벤트가 발생할 때마다.
  • ngOnDestroy 후크가 호출되면 구독이 취소됩니다(호스트 구성 요소가 파괴됨).

  • 또한 소비 애플리케이션이 가져올 Angular 모듈에 지시문을 제공해야 합니다.

    @NgModule({
      imports: [CommonModule],
      declarations: [SwipeDirective],
      exports: [SwipeDirective]
    })
    export class SwipeModule {}
    


    그건 그렇고, 이것은 no longer the only option 입니다. 우리는 아직 공공 도서관에서 독립 실행형 지침과 같은 최첨단 기능을 사용할 만큼 충분히 힙스터가 아닙니다.

    언급할 가치가 있는 몇 가지 사항




    zone.runOutsideAngular()

    공급자가 하나 더 삽입된 것을 눈치채셨을 것입니다.

    private zone: NgZone
    


    그리고 나중에 zone.runOutsideAngular에서 스와이프 구독을 래핑하는 데 사용됩니다. 이는 DOM에서 발생하는 모든 추적된 비동기 이벤트에서 불필요한 변경 감지 트리거를 피하는 일반적인 방법입니다. 우리의 경우 변경 감지가 모든mousemove 이벤트에서 과도하게 트리거되는 것을 원하지 않습니다.


    swipeMove 및 swipeEnd 모두 구독

    후드에서 사용한 ag-swipe-core 라이브러리의 공개 인터페이스는 onSwipeMoveonSwipeEnd 의 두 가지 이벤트 핸들러 중 하나만 제공할 수 있습니다. 하지만 Angular 래퍼에서는 추가 입력 매개변수를 피하고 항상 두 이벤트를 모두 처리하며 관심 있는 Output만 수신하도록 지시 소비자에게 맡깁니다.

    이 경우 가능한 성능 최적화보다 더 간단한 지시 계약을 선호하는 것은 의식적인 선택입니다. 합리적일 때 선택적인 최적화보다 단순성이 우선해야 한다고 생각하지만 물론 논의할 주제입니다.

    마무리



    this link의 GitHub에서 전체 라이브러리 코드를 찾을 수 있습니다.

    그리고 this link에 의한 npm 패키지.

    그거였다! 우리는 30줄의 코드로 스와이프 감지 라이브러리를 위한 간단한 Angular 지시문 래퍼를 구축했습니다. 스포일러 경고: React 버전은 더 짧아질 것입니다. 😄 그러나 다음 기사에서는 완전히 다른 이야기입니다.

    좋은 웹페이지 즐겨찾기