11 lip 2024
4 min

Angular: Zmienna szablonu @let – Hit czy Kit?

Niedawne ogłoszenie bloku @let w Angularze wywołało znaczną debatę w społeczności deweloperów. Podczas gdy niektórzy postrzegają go jako cenne uzupełnienie, inni uważają, że to zbędna komplikacja.

Argumenty za @let

Zwolennicy twierdzą, że @let upraszcza logikę szablonów, umożliwiając deklarowanie zmiennych bezpośrednio w szablonie, unikając problemów z wartościami “falsy” oraz poprawiając czytelność. Pozwala to na bardziej przejrzysty i czystszy kod, zwłaszcza przy pracy ze złożonymi warunkami i asynchronicznymi danymi.

Problem z wartościami “falsy”

Wcześniej, aby zadeklarować zmienną w szablonie Angulara, deweloperzy często używali dyrektywy ngIf ze słowem kluczowym as. Jednak ta metoda miała ograniczenie: wartości “falsy”, takie jak 0, puste stringi (""), null, undefined i false, uniemożliwiały renderowanie zawartości. Na przykład:

<div *ngIf="userName$ | async as userName">
  <h1>Witaj, {{ userName }}</h1>
</div>

Jeśli userName byłby pustym ciągiem, nic by się nie wyświetliło. Blok @let rozwiązuje ten problem:

<div>
  @let userName = (userName$ | async) ?? 'Gość';
  <h1>Witaj, {{ userName }}</h1>
</div>

Złożone szablony z dynamicznymi kolumnami

Kolejnym dobrym zastosowaniem tej funkcji są złożone szablony HTML, w których definicje kolumn i wartości wynikają ze złożonych konfiguracji. Każdy, kto pracował nad aplikacją biznesową z dużymi tabelami, zna te wyzwania. @let może znacząco uprościć zarządzanie tymi tabelami.

Z @let:

<table mat-table [dataSource]="dataSource">
  @for (columnDef of columnDefs) {
    @let property = columnDef.propertyName;
    <ng-container [matColumnDef]="columnDef.name">
      <th mat-header-cell *matHeaderCellDef>{{ columnDef.header }}</th>
      <td mat-cell *matCellDef="let element">
        @let cellValue = element[property];
        <ng-container *ngIf="columnDef.cellType === 'link'; else plainCell">
          <a [routerLink]="cellValue?.routerLink">{{ cellValue?.value }}</a>
        </ng-container>
        <ng-template #plainCell>{{ cellValue }}</ng-template>
      </td>
    </ng-container>
  }
</table>

Bez @let:

<table mat-table [dataSource]="dataSource">
  <ng-container *ngFor="let columnDef of columnDefs">
    <ng-container [matColumnDef]="columnDef.name">
      <th mat-header-cell *matHeaderCellDef>{{ columnDef.header }}</th>
      <td mat-cell *matCellDef="let element">
        <ng-container *ngIf="columnDef.cellType === 'link'; else plainCell">
          <a [routerLink]="element[columnDef.propertyName]?.routerLink">{{ element[columnDef.propertyName]?.value }}</a>
        </ng-container>
        <ng-template #plainCell>{{ element[columnDef.propertyName] }}</ng-template>
      </td>
    </ng-container>
  </ng-container>
</table>

Argumenty przeciw @let

Krytycy twierdzą, że blok @let wprowadza zbędną złożoność i może prowadzić do zamieszania. Oto kilka przykładów ilustrujących ich obawy:

  1. Zwiększone obciążenie poznawcze: Wprowadzenie @let dodaje kolejny koncept, którego deweloperzy muszą się nauczyć i zrozumieć. Może to zwiększyć obciążenie poznawcze, zwłaszcza dla nowych deweloperów, którzy już starają się pojąć rozbudowane funkcje Angulara.
  2. Potencjalne nadużycia: Istnieje ryzyko, że deweloperzy będą nadużywać lub źle wykorzystywać @let, prowadząc do szablonów, które są trudniejsze do odczytu i utrzymania. Na przykład, zagnieżdżanie wielu bloków @let w złożonych szablonach może sprawić, że kod będzie mniej przejrzysty. Podczas recenzji kodu konieczna będzie dodatkowa uwaga, aby upewnić się, że nie tworzy się zbędnych zmiennych szablonowych.
  3. Istniejące rozwiązania są wystarczające: Krytycy uważają, że istniejące funkcje Angulara, zwłaszcza możliwość konwersji observabli na sygnały, są wystarczające do obsługi większości przypadków użycia. Twierdzą, że wprowadzenie @let nie przynosi znaczących korzyści w porównaniu z tymi istniejącymi rozwiązaniami.

Przykład ilustrujący złożoność

Rozważmy scenariusz, w którym w szablonie deklarowanych jest wiele zmiennych. Użycie @let może sprawić, że szablon stanie się bardziej zagracony i trudniejszy do śledzenia:

<div>
  @let firstName = user?.firstName;
  @let lastName = user?.lastName;
  @let fullName = `${firstName} ${lastName}`;
  <p>{{ fullName }}</p>
  @if (user?.address) {
    @let street = user.address.street;
    @let city = user.address.city;
    <p>{{ street }}, {{ city }}</p>
  }
</div>

Choć ten przykład pokazuje potencjalną wygodę @let, ilustruje również, jak wielokrotne deklaracje @let mogą prowadzić do bałaganu w szablonie.

Moja opinia

Prawdopodobnie jestem gdzieś pośrodku. Na samym początku nie widziałem wielu przypadków użycia tej funkcji, zwłaszcza teraz, gdy mogę tworzyć sygnały z observabli i używać ich nie tylko w moim szablonie, ale także w moich plikach .ts, gdy tylko potrzebuję. Centralizuje to źródło moich wartości, pozwalając na ich ponowne użycie bez dodatkowej złożoności. Podczas refaktoryzacji mojego kodu, jeśli napotkam przypadek z *ngIf i składnią "as" z observablem, wolałbym użyć sygnału zamiast tworzenia zmiennej szablonu z @let.

Jednak przykład z tabelą (dzięki @skorupka_k za zwrócenie na to uwagi) przekonał mnie, że złożone tabele są bardzo dobrym miejscem do wykorzystania tej funkcji. Kiedykolwiek będę z nimi pracował ponownie, zdecydowanie rozważę użycie @let.

Ogólnie rzecz biorąc, wolałbym unikać jej używania i zachowałbym szczególną ostrożność podczas przeglądów kodu, aby upewnić się, że jest używana tylko wtedy, gdy jest to konieczne, ale mimo to lepiej mieć ją w Angularze niż nie!

Podsumowanie

Blok @let w Angularze to kontrowersyjna funkcja, przez jednych chwalona jako przełomowa, przez innych odrzucana jako zbędna. Czy jest hitem czy kitem, zależy ostatecznie od tego, jak deweloperzy zdecydują się ją zintegrować w swój workflow.

Jakie są Twoje myśli? Czy funkcjonalność @let to mile widziane uzupełnienie, czy zbędna komplikacja? Podziel się swoimi opiniami w komentarzach poniżej.

Źródło: [justangular.com](https://justangular.com/blog/template-local-variables-with-let-in-angular)

Podziel się artykułem

Zapisz się na nasz newsletter

Dołącz do community Angular.love i bądź na bieżąco z trendami.