@Directive и @Component в Angular: в чем разница и когда что использовать?
Главное отличие: @Component — это компонент с шаблоном, @Directive — это поведение без шаблона
Вы абсолютно правы: @Component наследуется от @Directive. Но ключевое различие — наличие шаблона (template). Компонент — это директива с собственным HTML-шаблоном, а обычная директива — это "поведение", которое вы применяете к существующему элементу.
Давайте разберем на вашем примере. У вас есть два подхода:
- Компонент — создает новый элемент DOM (например,
<app-hover-button>) с собственной разметкой и стилями. - Директива — изменяет поведение существующего элемента, к которому ее применяют (например,
<button appHoverHighlight>).
Когда использовать @Component?
Используйте @Component, когда вам нужно создать новую, самодостаточную единицу интерфейса с собственной версткой. Примеры:
- Форма входа
- Карточка товара
- Модальное окно
- Страница профиля
Пример правильного использования компонента:
@Component({
selector: 'app-user-card',
template: `
<div class="card">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
<button (click)="editUser()">Редактировать</button>
</div>
`,
styles: [`.card { border: 1px solid #ccc; padding: 10px; }`]
})
export class UserCardComponent {
@Input() user: User;
editUser() { /* логика редактирования */ }
}
Когда использовать @Directive?
Используйте @Directive, когда вам нужно добавить поведение к уже существующему элементу (кнопке, input, div). Директивы отлично подходят для:
- Изменения стилей при наведении (как в вашем примере)
- Валидации форм
- Обработки кликов/событий
- Манипуляции с DOM
Ваш пример с директивой — идеальный случай:
@Directive({
selector: '[appHoverHighlight]'
})
export class HoverHighlightDirective {
@HostBinding('style.backgroundColor') bgColor: string = 'transparent';
@HostListener('mouseenter') onHover() {
this.bgColor = 'yellow';
}
@HostListener('mouseleave') onLeave() {
this.bgColor = 'transparent';
}
}
// Использование в шаблоне:
// <button appHoverHighlight>Наведи на меня</button>
// <div appHoverHighlight>Или на этот блок</div>
Почему @Component — это подкласс @Directive?
В архитектуре Angular @Component расширяет @Directive для наследования общей функциональности: lifecycle hooks, dependency injection, host bindings/listeners. Но компонент добавляет:
- template (или templateUrl) — HTML-шаблон
- styles (или styleUrls) — изолированные стили
- changeDetection — стратегия обнаружения изменений
- viewProviders — провайдеры для view-детей
Итоговая рекомендация для вашего примера
Для изменения цвета кнопки при наведении используйте @Directive. Почему?
- Вы не создаете новый элемент — просто модифицируете существующую кнопку
- Директиву можно применить к любому элементу (кнопка, div, span)
- Код получается более переиспользуемым и легким
- Не нужно создавать лишнюю обертку в DOM
Запомните простое правило: если у вас есть собственный HTML-шаблон — это @Component. Если вы только добавляете поведение к существующему элементу — это @Directive.
<<Дополнительный взгляд: структурные и атрибутивные директивы
Коллега выше верно описал основное отличие, но стоит добавить, что директивы делятся на два типа, и это тоже помогает понять разницу с компонентами.
- Атрибутивные директивы — меняют внешний вид или поведение элемента. Ваш
appHoverHighlight— это атрибутивная директива. Другие примеры:ngClass,ngStyle,ngModel. - Структурные директивы — меняют структуру DOM (добавляют/удаляют элементы). Примеры:
*ngIf,*ngFor,*ngSwitch.
Компонент же — это всегда элемент с собственным шаблоном. Он ближе к структурной директиве, но с полноценной версткой.
Практический совет
Если вы сомневаетесь, задайте себе вопрос: "Могу ли я применить эту логику к любому HTML-элементу без изменения его внутренней структуры?" Если да — это директива. Если вам нужно создать новый элемент с уникальной разметкой — это компонент.
Также помните: компонент может использовать директивы внутри своего шаблона. Например, ваш компонент HoverButtonComponent мог бы внутри себя применить директиву appHoverHighlight к своей кнопке. Это демонстрирует их иерархию и разделение ответственности.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги