Что такое директивы структурные (*ngIf) и атрибутные?angular-54

Директивы в Angular — это специальные конструкции, которые добавляют дополнительное поведение элементам DOM. Они делятся на два основных типа: структурные и атрибутные.

Структурные директивы

Структурные директивы изменяют структуру DOM, добавляя или удаляя элементы. Их можно узнать по звездочке (*) в синтаксисе.

Особенности:

  • Меняют макет DOM
  • Всегда начинаются с *
  • Работают с <ng-template> под капотом
  • Управляют отображением групп элементов

Примеры:

1. *ngIf — условное отображение

<div *ngIf="isVisible; else notVisible">
  Контент виден
</div>

<ng-template #notVisible>
  <div>Альтернативный контент</div>
</ng-template>

2. *ngFor — перебор коллекции

<ul>
  <li *ngFor="let item of items; index as i; trackBy: trackById">
    {{i + 1}}. {{item.name}}
  </li>
</ul>

3. *ngSwitch — условный выбор

<div [ngSwitch]="userRole">
  <p *ngSwitchCase="'admin'">Админ-панель</p>
  <p *ngSwitchCase="'user'">Профиль пользователя</p>
  <p *ngSwitchDefault>Гостевая версия</p>
</div>

Атрибутные директивы

Атрибутные директивы изменяют внешний вид или поведение существующих элементов, не изменяя структуру DOM.

Особенности:

  • Не изменяют структуру DOM
  • Работают как обычные атрибуты
  • Модифицируют свойства элементов

Примеры:

1. ngClass — динамическое управление классами

<div [ngClass]="{
  'active': isActive,
  'disabled': isDisabled,
  'highlight': hasError
}"></div>

2. ngStyle — динамические стили

<button [ngStyle]="{
  'color': isPrimary ? 'white' : 'black',
  'background-color': buttonColor,
  'font-size.px': fontSize
}">Кнопка</button>

3. ngModel — двустороннее связывание

<input [(ngModel)]="userName" placeholder="Введите имя">

Различия между типами директив

Характеристика Структурные Атрибутные
Влияние на DOM Изменяют структуру Модифицируют элементы
Синтаксис Префикс * Обычные атрибуты
Примеры *ngIf, *ngFor, *ngSwitch ngClass, ngStyle, ngModel
Внутренняя реализация Работают с ng-template Работают с HostElement

Создание пользовательских директив

Атрибутная директива

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  @HostListener('mouseenter') onMouseEnter() {
    this.highlight('yellow');
  }

  constructor(private el: ElementRef) {}

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

Использование:

<p appHighlight>Наведи на меня</p>

Структурная директива

@Directive({
  selector: '[appRepeat]'
})
export class RepeatDirective {
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef
  ) {}

  @Input() set appRepeat(times: number) {
    this.viewContainer.clear();
    for (let i = 0; i < times; i++) {
      this.viewContainer.createEmbeddedView(this.templateRef, {
        $implicit: i + 1
      });
    }
  }
}

Использование:

<ng-template appRepeat="5" let-number>
  <p>Элемент {{number}}</p>
</ng-template>

Лучшие практики

  1. Для условий — используйте *ngIf вместо скрытия через CSS
  2. Для списков — всегда добавляйте trackBy в *ngFor
  3. Для стилей — предпочитайте ngClass вместо ngStyle, где возможно
  4. Для производительности — избегайте сложных вычислений в директивах

Резюмируем

структурные директивы (*ngIf, *ngFor) управляют структурой DOM, а атрибутные (ngClass, ngStyle) изменяют свойства существующих элементов. Понимание различий между ними позволяет эффективно управлять отображением и поведением компонентов в Angular-приложениях.