Декоратор — это специальная функция, которая модифицирует классы, методы, свойства или параметры, добавляя к ним метаданные или изменяя их поведение. В Angular встроенные декораторы (@Component
, @Injectable
, @Input
и др.) используются для определения метаданных классов.
export function Log() {
return function(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Вызван метод ${propertyKey} с аргументами:`, args);
const result = originalMethod.apply(this, args);
console.log(`Метод ${propertyKey} вернул:`, result);
return result;
};
return descriptor;
};
}
Использование:
@Component({...})
export class MyComponent {
@Log()
calculateSum(a: number, b: number): number {
return a + b;
}
}
export function AutoUnsubscribe() {
return function(constructor: any) {
const originalNgOnDestroy = constructor.prototype.ngOnDestroy;
constructor.prototype.ngOnDestroy = function() {
for (const prop in this) {
const property = this[prop];
if (property && typeof property.unsubscribe === 'function') {
property.unsubscribe();
}
}
originalNgOnDestroy?.apply(this);
};
};
}
Использование:
@AutoUnsubscribe()
@Component({...})
export class MyComponent implements OnDestroy {
data$ = someObservable.pipe(...);
ngOnDestroy() {
console.log('Компонент уничтожается');
}
}
export function Cache() {
return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const getter = descriptor.get;
if (!getter) throw new Error('@Cache можно применять только к геттерам');
const cacheKey = `__cached_${propertyKey}`;
descriptor.get = function() {
if (!this[cacheKey]) {
this[cacheKey] = getter.apply(this);
}
return this[cacheKey];
};
};
}
Использование:
@Component({...})
export class MyComponent {
private _heavyData: any;
@Cache()
get processedData() {
return this._heavyData.map(...); // Тяжелая операция
}
}
export function CheckPermission(permission: string) {
return function(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
if (!this.authService.hasPermission(permission)) {
throw new Error('Доступ запрещен!');
}
return originalMethod.apply(this, args);
};
};
}
Использование:
@Component({...})
export class AdminPanelComponent {
@CheckPermission('admin')
deleteUser(userId: string) {
// Логика удаления
}
}
Декораторы компилируются в runtime, поэтому:
babel-plugin-annotations
).Влияние на производительность: