Директивы в Angular играют ключевую роль в расширении функциональности приложений, позволяя манипулировать DOM-элементами и их поведением. В отличие от простых структурных и атрибутивных директив, которые используются для добавления или изменения элементов в шаблонах, директивы с параметрами обладают возможностью динамически изменять поведение этих элементов с учётом переданных данных.
Для того чтобы создать директиву с параметрами, нужно использовать
декоратор @Directive, а также определить её логику в
классе. Параметры, которые директива принимает, передаются через входные
свойства директивы. В Angular для этого используются декораторы
@Input().
import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() appHighlight: string;
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnChanges() {
this.renderer.setStyle(this.el.nativeElement, 'backgroundColor', this.appHighlight);
}
}
В данном примере директива HighlightDirective изменяет
цвет фона элемента в зависимости от переданного параметра
appHighlight. Этот параметр задается в шаблоне, где
используется данная директива.
После того как директива создана, её можно применять в шаблонах Angular-компонентов. Параметры директивы передаются через атрибуты, которые должны быть указаны в соответствующих элементах HTML.
<p [appHighlight]="'yellow'">Этот текст будет выделен желтым.</p>
В данном примере директива appHighlight меняет фон
элемента на желтый, потому что параметр 'yellow' передан в
директиву.
Если необходимо передавать несколько параметров в директиву, можно использовать несколько входных свойств. В этом случае каждый параметр будет указывать на отдельную переменную в классе директивы.
import { Directive, Input, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[appBorder]'
})
export class BorderDirective {
@Input() appBorderColor: string;
@Input() appBorderWidth: string;
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnChanges() {
this.renderer.setStyle(this.el.nativeElement, 'border', `${this.appBorderWidth} solid ${this.appBorderColor}`);
}
}
В этом примере директива BorderDirective принимает два
параметра: цвет и ширину рамки. При изменении этих значений стили
элемента будут обновляться.
<div [appBorderColor]="'blue'" [appBorderWidth]="'2px'">С этим элементом будет работать директива с несколькими параметрами.</div>
В случае, если параметры изменяются в ходе работы приложения,
директива автоматически обновляет свой стиль благодаря жизненному циклу
ngOnChanges. Этот хук вызывается каждый раз, когда значения
входных свойств изменяются. Это позволяет директивам реагировать на
изменения данных и динамически обновлять свой интерфейс.
Иногда требуется установить дефолтные значения для параметров директивы, чтобы обеспечить корректную работу компонента, даже если параметр не был явно передан. Это можно сделать в теле класса директивы.
import { Directive, Input, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[appTextColor]'
})
export class TextColorDirective {
@Input() appTextColor: string = 'black'; // Дефолтное значение
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnChanges() {
this.renderer.setStyle(this.el.nativeElement, 'color', this.appTextColor);
}
}
В случае, если параметр appTextColor не передан, текст
будет окрашен в черный цвет по умолчанию.
<p appTextColor>Текст будет черным, так как параметр не передан.</p>
<p [appTextColor]="'green'">Этот текст будет зеленым.</p>
Если параметр директивы представляет собой сложный объект, например, массив или объект, его можно изменить и передать новые значения. Важно помнить, что Angular будет отслеживать только изменения ссылок на объекты, а не их внутреннее содержимое. Поэтому для эффективной работы с такими параметрами следует использовать глубокие изменения или технику отслеживания изменений.
import { Directive, Input, ElementRef, Renderer2, OnChanges, SimpleChanges } from '@angular/core';
@Directive({
selector: '[appStyleChanges]'
})
export class StyleChangesDirective implements OnChanges {
@Input() appStyleChanges: { color?: string; fontSize?: string };
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnChanges(changes: SimpleChanges) {
if (changes['appStyleChanges']) {
const { color, fontSize } = this.appStyleChanges;
if (color) {
this.renderer.setStyle(this.el.nativeElement, 'color', color);
}
if (fontSize) {
this.renderer.setStyle(this.el.nativeElement, 'fontSize', fontSize);
}
}
}
}
В этом примере директива StyleChangesDirective принимает
объект с параметрами color и fontSize. При
изменении этого объекта стили элемента автоматически обновляются.
<p [appStyleChanges]="{color: 'blue', fontSize: '20px'}">Этот текст будет синим и крупным.</p>
При работе с директивами с параметрами важно учитывать особенности
жизненного цикла Angular. Особенно это касается асинхронных изменений и
обновлений данных. Чтобы избежать лишних перерисовок и ненужных
вычислений, можно использовать различные стратегии оптимизации, такие
как ngOnChanges, ngDoCheck и другие хуки
жизненного цикла, которые позволяют точно контролировать, когда и как
следует обновлять параметры и состояние директивы.
Директивы с параметрами являются важным инструментом для динамического изменения поведения элементов в Angular-приложениях. Понимание того, как передавать параметры, работать с их изменениями и устанавливать дефолтные значения, позволяет разрабатывать гибкие и эффективные интерфейсы.