Skip to content

装饰器

装饰器简介

装饰器(Decorator)是一种特殊类型的声明,它能够被附加到类声明方法访问符属性参数上。装饰器使用 @expression 这种形式,expression 求值后必须为一个函数,它在运行时被调用,被装饰的声明信息会作为参数传入。

常用装饰器类型

类装饰器

typescript
function classDecorator(constructor: Function) {
  // 可以修改类的属性和方法
}

@classDecorator
class Example {
  // ...
}

方法装饰器

typescript
function methodDecorator(
  target: any,
  propertyKey: string,
  descriptor: PropertyDescriptor
) {
  // 可以修改方法的实现
}

class Example {
  @methodDecorator
  method() {}
}

属性装饰器

typescript
function propertyDecorator(target: any, propertyKey: string) {
  // 可以修改属性的元数据
}

class Example {
  @propertyDecorator
  property: string;
}

实现依赖注入

使用装饰器实现简单的依赖注入容器:

typescript
// 存储元数据的容器
const Container = new Map();

// 注入装饰器
function Injectable() {
  return function (target: any) {
    Container.set(target.name, target);
  };
}

// 使用示例
@Injectable()
class UserService {
  getUsers() {
    return ['user1', 'user2'];
  }
}

@Injectable()
class UserController {
  constructor(private userService: UserService) {}
}

反射元数据

结合 reflect-metadata 库使用装饰器可以实现更强大的功能:

typescript
import 'reflect-metadata';

// 定义元数据装饰器
function Module(metadata: any) {
  return function (target: any) {
    Reflect.defineMetadata('module', metadata, target);
  };
}

// 使用示例
@Module({
  controllers: [UserController],
  providers: [UserService],
})
class AppModule {}

最佳实践

  1. 装饰器应该保持简单和单一职责
  2. 使用装饰器工厂函数来传递参数
  3. 注意装饰器的执行顺序
  4. 合理使用反射元数据扩展功能

注意事项

  1. 装饰器是实验性特性,需要在 tsconfig.json 中启用 experimentalDecorators
  2. 装饰器执行时机是在类定义时,而不是实例化时
  3. 多个装饰器组合时,执行顺序是从下到上