Как использовать *ngIf else в Angular
Узнайте, как использовать *ngIf else в Angular для более чистого условного рендеринга. Изучите синтаксис, примеры, лучшие практики и преимущества производительности по сравнению с отдельными элементами *ngIf.
Как использовать *ngIf else в Angular?
Я работаю с Angular и хочу реализовать директиву *ngIf else (доступную начиная с версии 4) для условного отображения контента. В настоящее время я использую отдельные элементы div с противоположными условиями:
<div *ngIf="isValid">
контент здесь ...
</div>
<div *ngIf="!isValid">
другой контент здесь...
</div>
Как я могу добиться того же поведения, используя синтаксис ngIf else, чтобы сделать мой код более лаконичным и поддерживаемым?
Директива *ngIf else в Angular позволяет более лаконично условно отображать контент, используя одно условие со ссылкой на шаблон else, что устраняет необходимость в отдельных элементах div с противоположными условиями. Этот синтаксис доступен с Angular 4 и обеспечивает лучшую производительность и более чистую структуру кода, сохраняя связанный условный контент вместе в ваших шаблонах. Вместо управления двумя отдельными директивами *ngIf с отрицательными условиями, вы можете использовать синтаксис *ngIf="condition; else templateName" в паре с элементом ng-template для определения контента запасного варианта.
Содержание
- Базовый синтаксис *ngIf Else
- Работа с ng-template
- Расширенные примеры и лучшие практики
- Рекомендации по производительности
- Миграция с отдельных элементов *ngIf
- Полный пример компонента
Базовый синтаксис *ngIf Else
Фундаментальный синтаксис *ngIf else следует этому шаблону:
<div *ngIf="condition; else elseBlockName">
<!-- Контент для отображения, когда условие истинно -->
<p>Этот контент отображается, когда условие истинно</p>
</div>
<ng-template #elseBlockName>
<!-- Контент для отображения, когда условие ложно -->
<p>Этот контент отображается, когда условие ложно</p>
</ng-template>
Основные компоненты:
*ngIf="condition; else elseBlockName"- Основная директива с предложением else<ng-template #elseBlockName>- Шаблон, содержащий контент запасного варианта#elseBlockNameсоздает переменную ссылки на шаблон, к которой может обращаться директива *ngIf
Как объясняется в документации Angular, “Когда выражение оценивается как истинное, Angular отображает шаблон, предоставленный в предложении then, а когда ложно или null, Angular отображает шаблон, предоставленный в необязательном предложении else.”
Работа с ng-template
Элемент ng-template является ключевым для функциональности *ngIf else. Это специальный элемент Angular, который интерпретируется во время выполнения, но сам не отображается в DOM.
Вот как это работает:
<!-- Пример аутентификации пользователя -->
<div *ngIf="isLoggedIn; else loginPrompt">
<h2>Добро пожаловать обратно, пользователь!</h2>
<p>Вы успешно вошли в систему.</p>
</div>
<ng-template #loginPrompt>
<div class="login-container">
<h2>Пожалуйста, войдите в систему для продолжения</h2>
<button (click)="login()">Войти</button>
</div>
</ng-template>
Как объясняется в уроке на malcoded.com, “ng-template - это специальный элемент, который интерпретируется Angular и не имеет соответствия в DOM. Это означает, что этот тег не включается в итоговый HTML-результат, а только его содержимое.”
Вы также можете использовать переменные шаблона для создания более сложных условных структур:
<div *ngIf="userRole === 'admin'; else userTemplate">
<h2>Панель администратора</h2>
<p>Добро пожаловать в административный интерфейс</p>
</div>
<ng-template #userTemplate>
<div *ngIf="userRole === 'editor'; else guestTemplate">
<h2>Панель редактора</h2>
<p>Добро пожаловать в интерфейс редактирования</p>
</div>
</ng-template>
<ng-template #guestTemplate>
<h2>Публичный контент</h2>
<p>Пожалуйста, войдите в систему для доступа к дополнительным функциям</p>
</ng-template>
Расширенные примеры и лучшие практики
Использование ngIf с предложениями then и else
Для большего контроля вы можете явно использовать предложение then:
<ng-template #adminTemplate let-user="user">
<h2>Администратор: {{ user.name }}</h2>
<p>Предоставлен полный административный доступ</p>
</ng-template>
<ng-template #defaultTemplate let-user="user">
<h2>Добро пожаловать: {{ user.name }}</h2>
<p>Стандартный пользовательский доступ</p>
</ng-template>
<div *ngIf="user; then adminTemplate; else defaultTemplate" [ngIfContext]="user">
</div>
Условный рендеринг на основе данных
Для сценариев, таких как отображение списков курсов или коллекций данных:
<div *ngIf="courses.length > 0; else noCoursesTemplate">
<h2>Ваши курсы</h2>
<ul>
<li *ngFor="let course of courses">{{ course.name }}</li>
</ul>
</div>
<ng-template #noCoursesTemplate>
<div class="empty-state">
<h2>Курсы недоступны</h2>
<button (click)="browseCourses()">Обзор курсов</button>
</div>
</ng-template>
Как объясняется в руководстве Angular University, “Помимо выражения courses.length, мы также можем передать в ngIf предложение else, которое указывает на ссылку на шаблон (шаблон noCourses в данном случае).”
Переменные контекста шаблона
Вы можете передавать переменные контекста в ваши шаблоны:
<ng-template #userTemplate let-user="user" let-role="role">
<div class="user-card">
<h3>{{ user.name }}</h3>
<p>Роль: {{ role }}</p>
</div>
</ng-template>
<div *ngIf="currentUser; then userTemplate; else guestTemplate"
[ngIfContext]="{user: currentUser, role: currentUser.role}">
</div>
Рекомендации по производительности
Синтаксис *ngIf else предлагает преимущества производительности по сравнению с использованием отдельных директив *ngIf с отрицательными условиями. Согласно результатам исследований, Angular 17+ показал “ускорение производительности времени выполнения до 90%” с этим подходом.
Ключевые преимущества производительности включают:
- Единая оценка директивы: Вместо оценки двух отдельных условий *ngIf, Angular оценивает только одно условие и связанную с ним ссылку на шаблон
- Лучшее обнаружение изменений: Фреймворк может более эффективно отслеживать изменения и обновлять DOM
- Эффективность использования памяти: Только активный шаблон создается экземпляром и хранится в памяти
В обсуждении на Stack Overflow упоминается, что “с точки зрения производительности, я подозреваю, что первый вариант имеет 2 директивы, которые нужно оценивать независимо, в то время как другие 2 имеют только одну. Если бы у вас это было в списке/таблице из тысяч элементов, не было бы это медленнее?”
Миграция с отдельных элементов *ngIf
Миграция с текущего подхода с использованием отдельных элементов div проста:
До (текущий подход):
<div *ngIf="isValid">
контент здесь ...
</div>
<div *ngIf="!isValid">
другой контент здесь...
</div>
*После (использование ngIf else):
<div *ngIf="isValid; else invalidContent">
контент здесь ...
</div>
<ng-template #invalidContent>
другой контент здесь...
</ng-template>
Процесс миграции включает:
- Определение пар условий *ngIf, которые являются противоположными
- Выбор одного в качестве основного условия
- Создание ng-template для блока else
- Ссылка на шаблон в директиве *ngIf
Полный пример компонента
Вот полный пример, показывающий компонент профиля пользователя с *ngIf else:
import { Component } from '@angular/core';
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html'
})
export class UserProfileComponent {
isLoggedIn = true;
userRole = 'admin';
isLoading = false;
userProfile = null;
constructor() {
// Имитация загрузки данных пользователя
setTimeout(() => {
this.isLoading = false;
this.userProfile = {
name: 'John Doe',
email: 'john@example.com',
role: 'admin'
};
}, 2000);
}
logout() {
this.isLoggedIn = false;
}
}
<!-- user-profile.component.html -->
<div *ngIf="!isLoading; else loadingTemplate">
<div *ngIf="isLoggedIn; else notLoggedInTemplate">
<div *ngIf="userProfile.role === 'admin'; else regularUserTemplate">
<h2>Панель администратора</h2>
<p>Добро пожаловать обратно, {{ userProfile.name }}!</p>
<button (click)="logout()">Выйти</button>
</div>
<ng-template #regularUserTemplate>
<h2>Панель пользователя</h2>
<p>Добро пожаловать обратно, {{ userProfile.name }}!</p>
<p>Ваша роль: {{ userProfile.role }}</p>
<button (click)="logout()">Выйти</button>
</ng-template>
</div>
<ng-template #notLoggedInTemplate>
<div class="login-prompt">
<h2>Пожалуйста, войдите в систему для продолжения</h2>
<p>Вам необходимо войти в систему для доступа к вашему профилю.</p>
</div>
</ng-template>
</div>
<ng-template #loadingTemplate>
<div class="loading-spinner">
<p>Загрузка вашего профиля...</p>
</div>
</ng-template>
Этот пример демонстрирует:
- Вложенные операторы *ngIf else
- Состояния загрузки с ng-template
- Условный рендеринг на основе роли пользователя
- Четкое разделение различных состояний UI
Источники
- NgIf • Документация Angular
- Как использовать “*ngIf else” в Angular с примерами - OneClickITSolution
- Как использовать *ngIf else в Angular - malcoded.com
- Как можно использовать “*ngIf else”? - Medium от Daniel Martin
- Angulars NgIf, Else, Then - Объяснено - Ultimate Courses
- Angular ngIf: Полное руководство - Angular University
- Понимание *ngIf, *ngIf else, *ngIf then else - Medium от InterviewPro
Заключение
Директива *ngIf else обеспечивает более элегантный и производительный способ обработки условного рендеринга в приложениях Angular. Заменяя отдельные элементы div с противоположными условиями, вы можете достичь более чистого кода, который легче поддерживать и понимать. Ключевые преимущества включают лучшую производительность, улучшаемую читаемость и более эффективное обнаружение изменений. При реализации этого шаблона помните об использовании элементов ng-template для ваших блоков else и рассмотрите возможность использования переменных контекста шаблона для более сложных сценариев. Этот подход был усовершенствован в версиях Angular и продолжает улучшаться, с значительным повышением производительности в последних версиях, таких как Angular 17+.