NgRx 구성 요소로 반응형 Angular 템플릿 구축

13195 단어 angularngrxrxjs
이 기사에서는 고성능 방식으로 반응형 Angular 템플릿을 빌드하는 데 사용되는 @ngrx/component 라이브러리를 살펴보겠습니다. 여기에는 관찰 가능한 이벤트를 렌더링하는 데 주로 사용되는 선언 가능 집합이 포함되어 있으며 영역 전체 모드와 영역 없는 모드에서 모두 작동할 수 있습니다.

설치


@ngrx/component 패키지를 설치하려면 다음 명령 중 하나를 실행하십시오.

// Angular CLI
ng add @ngrx/component

// NPM
npm i @ngrx/component

// Yarn
yarn add @ngrx/component



푸시 파이프


ngrxPush 파이프는 템플릿에서 관찰 가능한 값을 표시하는 데 사용됩니다. 이를 사용하려면 PushModule를 Angular 모듈 또는 독립 실행형 구성 요소로 가져옵니다.

import { PushModule } from '@ngrx/component';

@Component({
  // ... other metadata
  standalone: true,
  imports: [
    // ... other imports
    PushModule,
  ],
})
export class ProductDetailsComponent {
  readonly product$ = this.store.select(selectActiveProduct);

  constructor(private readonly store: Store) {}
}


💡 PushModule is available since version 14. If you're using an older version of the @ngrx/component package, import the ReactiveComponentModule.


ngrxPush 파이프는 async 파이프의 대안이며 다음과 같은 방식으로 사용할 수 있습니다.

<ngrx-product-form
  [product]="product$ | ngrxPush"
></ngrx-product-form>

async 파이프와 마찬가지로 ngrxPush 파이프는 전달된 Observable의 마지막 방출 값을 반환하거나 방출 값이 없는 경우 undefined를 반환합니다. 그러나 async 파이프와 비교할 때 두 가지 주요 차이점이 있습니다.
  • ngrxPush 파이프는 Observable이 동일한 값을 연속으로 내보낼 때 변경 감지를 트리거하지 않습니다.
  • ngrxPush 파이프는 Observable이 영역 없는 모드에서 새 값을 내보낼 때 변경 감지를 트리거합니다.

  • 💡 Since version 14, the @ngrx/component package uses the global rendering strategy in both zone-full and zone-less mode. In previous versions, it used the native local rendering strategy in zone-less mode, which caused performance issues.




    Let 지시어


    *ngrxLet 지시문은 템플릿에서 관찰 가능한 이벤트를 렌더링하는 데 사용됩니다. 이를 사용하려면 LetModule를 Angular 모듈 또는 독립 실행형 구성 요소로 가져옵니다.

    import { LetModule } from '@ngrx/component';
    
    @Component({
      // ... other metadata
      standalone: true,
      imports: [
        // ... other imports
        LetModule,
      ],
    })
    export class ProductListComponent {
      readonly products$ = this.productsService.getProducts({ limit: 10 });
      readonly totalCount$ = this.productsService.getTotalCount();
    
      constructor(private readonly productsService: ProductsService) {}
    }
    


    💡 LetModule is available since version 14. If you're using an older version of the @ngrx/component package, import the ReactiveComponentModule.


    *ngrxLet 지시문은 다음과 같은 방식으로 사용할 수 있습니다.

    <ng-container *ngrxLet="totalCount$ as totalCount">
      <h2>Products ({{ totalCount }})</h2>
    
      <p *ngIf="!totalCount" class="info-alert">
        There are no products.
      </p>
    </ng-container>
    


    처음에는 *ngIf 지시문과 async 파이프를 사용하여 동일한 결과를 얻을 수 있는 것 같습니다.

    <ng-container *ngIf="totalCount$ | async as totalCount">
      <h2>Products ({{ totalCount }})</h2>
    
      <p *ngIf="!totalCount" class="info-alert">
        There are no products.
      </p>
    </ng-container>
    


    그러나 *ngIf 지시문은 totalCount가 0(참 값)이 아닌 경우에만 포함된 뷰를 생성하고 0(거짓 값)인 경우에는 생성하지 않습니다. 반면에 *ngrxLet 지시문은 observable이 참인지 거짓인지에 관계없이 값을 내보낼 때 포함된 뷰를 생성합니다.

    다른 관찰 가능한 이벤트 추적


    *ngrxLet 지시문은 현재 관찰 가능한 상태를 기반으로 다른 콘텐츠를 표시하는 기능을 제공합니다. 예를 들어 observable이 오류 이벤트를 방출하면 오류 경고를 표시할 수 있습니다.

    <ng-container *ngrxLet="products$ as products; $error as error">
      <ngrx-product-card
        *ngFor="let product of products"
        [product]="product"
      ></ngrx-product-card>
    
      <p *ngIf="error" class="error-alert">{{ error.message }}</p>
    </ng-container>
    


    💡 Displaying thrown error is possible since version 14. In previous versions, the value of $error is true when the passed observable emits the error event.



    오류 외에도 전체 이벤트를 추적할 수 있습니다.

    <ng-container
      *ngrxLet="saveProgress$ as progress; $complete as complete"
    >
      <mat-progress-spinner
        [value]="progress"
        mode="determinate"
      ></mat-progress-spinner>
    
      <p *ngIf="complete" class="success-alert">
        Product is successfully saved!
      </p>
    </ng-container>
    


    미정산 템플릿 사용



    또한 서스펜스 템플릿을 *ngrxLet 지시문에 전달하는 옵션이 있습니다.

    <ng-container *ngrxLet="products$ as products; suspenseTpl: loading">
      <ngrx-product-card
        *ngFor="let product of products"
        [product]="product"
      ></ngrx-product-card>
    </ng-container>
    
    <ng-template #loading>
      <mat-spinner></mat-spinner>
    </ng-template>
    


    서스펜스 템플릿은 전달된 관찰 가능 항목이 서스펜스 상태일 때 렌더링됩니다. 위의 예에서 로딩 스피너는 products$ observable이 제품 목록을 내보낼 때까지 표시됩니다. 이 경우 로딩 스피너가 DOM에서 제거되고 제품이 표시됩니다.

    💡 Using suspense template with the *ngrxLet directive is available since version 14.



    관찰할 수 없는 값에 대한 별칭 사용



    관찰 가능 항목 및 약속 외에도 *ngrxLet 지시문은 정적(관찰 불가능) 값을 입력 인수로 허용할 수도 있습니다. 이 기능은 깊이 중첩된 속성에 별칭을 사용하여 읽을 수 있는 템플릿을 만드는 기능을 제공합니다.

    <ng-container *ngrxLet="productForm.controls.price as price">
      <input type="number" [formControl]="price" />
    
      <ng-container *ngIf="price.errors && (price.touched || price.dirty)">
        <p *ngIf="price.errors.required">Price is a required field.</p>
        <p *ngIf="price.errors.min">Price cannot be a negative number.</p>
      </ng-container>
    </ng-container>
    


    💡 Passing non-observable values to the *ngrxLet directive is available since version 14.




    요약



    많은 새롭고 강력한 기능이 버전 14에 추가되었습니다.
  • LetDirectivePushPipe에 대한 별도의 모듈
  • 템플릿에 내보낸 오류 표시
  • 관찰할 수 없는 값에 대한 별칭 사용
  • 템플릿에서 서스펜스 상태 처리
  • LetDirectivePushPipe에 대한 강력한 유형 지정

  • 또한 이 라이브러리는 더 나은 성능을 위해 거의 완전히 재작성되었습니다. 이전에 사용해 본 적이 없다면 사용해 보고 소감을 알려주세요!

    그건 그렇고, @ngrx/component 패키지는 최근 NPM에서 주당 30k 다운로드에 도달했습니다! 🎉



    자원


  • Official docs of the @ngrx/component package

  • 피어 리뷰어



    이 기사에 대한 유용한 제안을 해주셔서 감사합니다!

    좋은 웹페이지 즐겨찾기