В чем разница между @Directive и @Component в Angular?
Основное различие: Компонент — это Директива с шаблоном
Вы абсолютно правы: @Component — это подкласс @Directive. Это ключевой момент. Компонент наследует все возможности директивы (например, работу с @Input, @Output, хуками жизненного цикла) и добавляет одну критическую вещь — собственный шаблон (template).
Простыми словами:
- Директива (@Directive) — это "поведение", которое вы навешиваете на существующий DOM-элемент. Она не создает новый элемент, а модифицирует или расширяет уже имеющийся.
- Компонент (@Component) — это "новый элемент" со своей логикой, шаблоном и стилями. Вы используете его как тег в HTML (например,
<app-my-button></app-my-button>).
Когда использовать @Directive?
Директивы идеальны для:
- Изменения внешнего вида элемента (например, подсветка, скрытие, добавление CSS-классов).
- Обработки событий на элементе (клики, наведение мыши, drag-and-drop).
- Создания абстрактных поведений, которые можно переиспользовать на разных элементах.
Пример структурной директивы (изменяет DOM):
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[appShowIfAdmin]'
})
export class ShowIfAdminDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef
) {}
@Input() set appShowIfAdmin(isAdmin: boolean) {
if (isAdmin) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}
}
// Использование в шаблоне:
// <div *appShowIfAdmin="isAdmin">Только для админов</div>
Когда использовать @Component?
Компоненты — это "кирпичики" вашего приложения. Используйте их, когда:
- Нужен самостоятельный элемент интерфейса (кнопка, карточка, форма, модальное окно).
- Элемент имеет собственный шаблон и стили.
- Вы хотите создать переиспользуемый блок с четкой границей (инкапсуляция).
Пример компонента:
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-alert',
template: `
<div class="alert" [class.alert-danger]="type === 'error'">
{{ message }}
<button (click)="close.emit()">Закрыть</button>
</div>
`,
styles: [`
.alert { padding: 10px; border: 1px solid #ccc; }
.alert-danger { background: #f8d7da; border-color: #f5c6cb; }
`]
})
export class AlertComponent {
@Input() message: string = '';
@Input() type: 'info' | 'error' = 'info';
@Output() close = new EventEmitter<void>();
}
Резюме
Запомните простое правило:
- Если вы пишете
templateилиtemplateUrl— используйте @Component. - Если вы только добавляете поведение к существующему элементу (меняете класс, обрабатываете события, добавляете/убираете элементы) — используйте @Directive.
Ваш пример с кнопкой — это классический случай для @Component, потому что вы создаете новый элемент интерфейса с собственным шаблоном. Директива же не может "создать" кнопку, она может только изменить уже существующую.
<<Дополнение: Атрибутивные vs Структурные директивы
Стоит также различать два типа директив, которые часто путают с компонентами:
- Атрибутивные директивы — меняют внешний вид или поведение элемента. Примеры:
ngClass,ngStyle, ваша собственнаяappHighlight. Они работают как атрибуты. - Структурные директивы — меняют структуру DOM (добавляют/удаляют элементы). Примеры:
*ngIf,*ngFor,ngSwitch. Они используют звездочку*в синтаксисе.
Компоненты же — это третий тип, который всегда создает новый элемент и имеет свой собственный DOM. Ни одна директива не может заменить компонент, если вам нужно создать независимый UI-блок с шаблоном.
Совет для новичков: если сомневаетесь, начинайте с @Component. Вы всегда сможете рефакторингом вынести логику в директиву, если заметите, что она используется как поведение без собственного шаблона.