Angular Control Flow
В этой статье мы углубимся в новый поток управления, который был добавлен в 17 версии и который заставит вас забыть о таких директивах, как ngIf, ngSwitch и ngFor, благодаря новому синтаксису для написания операторов if , if/else и switch , а также цикла for в нашем шаблоне.
@if условие
Чтобы отобразить блок шаблона на основе условия, всегда использовалась директива ngIf :
@Component({ standalone: true, template: `<div *ngIf="condition"> ... </div>`, imports: [NgIf] }) export class MyComponent {}
У этой простой директивы действительно есть некоторые минусы :
- Синтаксис неинтуитивен и очень связан с инфраструктурой;
- Невозможно применить его к группам элементов, для этого вам нужно обернуть элементы внутри контейнера или ng-template / ng-container ;
- Вам необходимо импортировать CommonModule или директиву NgIf в ваши модули.
Новое условие @if позволяет получить тот же результат:
@if (condition) { * your content * }Язык кода: HTML, XML ( xml )
@if предлагает вам более чистый синтаксис, условные блоки сразу выделяются при чтении шаблона, что позволяет вам заключать группы элементов в фигурные скобки и, самое главное: больше не нужно импортировать модули или директивы .
@else и @else/if
условие if/else всегда было проблемой в Angular:
<div *ngIf="condition; else otherTemplate"> * your content * </div> <ng-template #otherTemplate> * your other content * </ng-template>
Потребность в ng-шаблоне в сочетании с переменной шаблона для предоставления в директиве ngIf резервного блока всегда была сложной и не очень немедленной.
И вот здесь @if помогает больше всего: его можно расширить с помощью @else :
@if (condition) { * your content * } @else { * your other content * }
Но дело не только в этом: @if можно еще больше расширить с помощью @else/if :
@if (condition) { * your content * } @else if (secondCondition) { * your second content * } @else { * your other content * }
Благодаря этому вы можете создавать шаблоны со сложными условиями, написав чистый и интуитивно понятный код. Легко читается, прост в обслуживании.
Теперь давайте продолжим с @switch .
@switch условие
До сегодняшнего дня директива ngSwitch использовалась для отображения определенного блока шаблона в списке на основе условия переключения:
<div [ngSwitch]="condition"> <div *ngSwitchCase="value1">* content block value1 *</div> <div *ngSwitchCase="value2">* content block value2 *</div> <div *ngSwitchDefault>* default content *</div> </div>
Аналогично @if, теперь есть совершенно новое условие @switch :
@switch(condition) { @case ('value1') { * content block value1 * } @case ('value2') { * content block value2 * } @default { * default content * } }
В этом случае вы можете получить более чистый синтаксис и отказаться от импорта .
Вот мы и подошли к последней теме: цикл @for .
@for цикл
Отображение списка блоков в шаблоне для представления списка элементов является ключевой концепцией многих фреймворков, и в Angular эту задачу можно выполнить с помощью директивы ngFor :
<ul> <li *ngFor="let item of itemList"> {{ item.name }} </li> </ul>
Эта директива позволяет вам создать индивидуальный блок для каждого элемента списка благодаря возможности использовать информацию об одном элементе и некоторых локальных переменных, предоставляемых самой директивой:
index: number
: индекс элемента в списке;count: number
: длина списка;first: boolean
: true, если элемент является первым в списке;last: boolean
: true, если элемент является последним в списке;even: boolean
: true, если индекс элемента четный;odd: boolean
: true, если индекс элемента нечетный.
Кроме того, директива ngFor принимает функцию trackBy в качестве необязательного параметра, используемого для предоставления Angular уникального идентификатора для каждого элемента списка (например, идентификатора):
<ul> <li *ngFor="let item of itemList; trackBy: itemById"> {{ item.name }} </li> </ul>Язык кода: HTML, XML ( xml ) itemById(index, item) { return item.id; }
Благодаря этому Angular может оптимизировать производительность при замене списка или изменении элемента.
Итак, чтобы заменить директиву ngFor, новый поток управления предоставляет @for :
<ul> @for (item of itemList; track item.id; let idx = $index, e = $even) { <li>{{ item.name }}</li> } </ul>
Этот новый синтаксис вносит некоторые важные изменения:
- Улучшение производительности до 90% по сравнению с ngFor благодаря новому алгоритму, используемому для реализации @for ;
- Функция trackBy заменяется свойством track , которое требует предоставления выражения, которое легче писать и читать, чем целую функцию;
- Свойство track необходимо , чтобы мы не забыли его, как это обычно происходит с функцией trackBy;
- Локальные переменные теперь имеют префикс $ (например: $index ).
Кроме того, вы также можете получить более чистый синтаксис и отказаться от импорта .
@empty блок
Мы можем добавить @empty
блок под @for
блоком. Содержимое @empty
блока отображается, если коллекция, которую мы передали в @for
блок, пуста:
<ul> @for (item of emptyCollection; track item.id;) { <li><strong>{{item.name}}</strong></li> } @empty { <span>The collection is empty</span> } </ul>
Заключение
Как вы можете видеть, новый поток управления предлагает новый способ написания сложных шаблонных условий в наших приложениях Angular, что обеспечивает повышение производительности и более удобный в обслуживании код.