Структурные директивы (те, что с *, например *ngIf/) изменяют DOM, . — это синтаксический сахар — под капотом Angular оборачивает элемент в , а директива контролирует, когда и как этот шаблон будет отрисован.
Структурные директивы (те, что с *, например *ngIf/) изменяют DOM, . — это синтаксический сахар — под капотом Angular оборачивает элемент в , а директива контролирует, когда и как этот шаблон будет отрисован.
*ngFor*<ng-template><!-- what you write -->
<p *ngIf="isVisible">Hello</p>
<!-- what Angular actually does -->
<ng-template [ngIf]="isVisible">
<p>Hello</p>
</ng-template>
* говорит Angular: "оберните этот элемент в шаблон и позвольте директиве решить, когда его добавить в DOM." <ng-template> — это инертный кусок разметки, который не отрисовывается, пока директива его не инстанцирует.
import { Directive, Input, TemplateRef, ViewContainerRef } from "@angular/core";
@Directive({ selector: "[appUnless]" }) // *appUnless = "the opposite of ngIf"
export class UnlessDirective {
constructor(
private templateRef: TemplateRef<any>, // the wrapped <ng-template>
private viewContainer: ViewContainerRef, // where to render it
) {}
@Input() set appUnless(condition: boolean) {
if (!condition) {
this.viewContainer.createEmbeddedView(this.templateRef); // render it
} else {
this.viewContainer.clear(); // remove it
}
}
}
// usage: <p *appUnless="isHidden">Shown when isHidden is false</p>
Два внедренных компонента являются ключевыми: TemplateRef — это шаблон элемента ("что отрисовать"), а ViewContainerRef — это местоположение в DOM ("где"). Директива вызывает createEmbeddedView для добавления элемента или clear для его удаления.
<!-- newer Angular replaces *ngIf/*ngFor with built-in block syntax -->
@if (isVisible) { <p>Hello</p> } @else { <p>Hidden</p> }
@for (item of items; track item.id) { <li>{{ item.name }}</li> }
Этот более новый синтаксис более читаем и производителен, хотя базовая концепция добавления/удаления остается той же.
Понимание развертывания * → <ng-template> демистифицирует, как *ngIf/*ngFor добавляют и удаляют DOM, и позволяет вам создавать пользовательские структурные директивы (используя TemplateRef + ViewContainerRef) для продвинутого управления шаблонами — например, отрисовка на основе прав доступа, пользовательские итераторы или ленивое добавление элементов.
Оно также уточняет, почему вы не можете размещать две структурные директивы (*ngIf и *ngFor) на одном элементе: каждой нужна своя обертка шаблона.
Библиотека вопросов для IT-собеседований с подробными ответами — от Junior до Senior.
Поддержать