介绍
随着 TypeScript 和 ES6 中类的引入,现在存在某些需要附加功能来支持注释或修改类和类成员的场景。 装饰器提供了一种为类声明和成员添加注释和元编程语法的方法。
命令行: tsc --target ES5 --experimentalDecorators
tsconfig.json:
{
"compilerOptions":{
"target": "es2016",
"experimentalDecorators": true,
}
}
装饰器类型
在 TypeScript 中,有4种类型的装饰器:
- 类装饰器(Class Decorators):应用于类构造函数,可用于观察、修改或替换类定义。被写在一个类声明之前,紧靠着类声明。
- 属性装饰器(Property Decorators):应用于类的属性声明。可以观察和修改类的属性定义。被写在一个属性声明之前。
- 方法装饰器(Method Decorators):应用于类的方法声明。可以观察、修改或替换方法定义。并可用来处理类中的方法及其参数。被写在一个方法声明之前。
- 参数装饰器(Parameter Decorators):应用于类构造函数或方法的参数。可以对类的成员方法的参数进行操作。
注意:装饰器是一种特殊类型的声明,能够被附加到类声明、方法、属性或参数上,可以修改它们的行为或值。
类装饰器(Class Decorators)
类的装饰器:是一种与类(class)相关的语法,用来注释或修改类和类方法,装饰器本身是一个函数,装饰器通过@来使用.
//注意装饰器的执行时机,不是在 创建实例的时候运行,而是在类创建的时候就会执行。
function testDec(constructor: any) {
console.log("123");
}
@testDec
class Person {}
//装饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,装饰器能在编译阶段运行代码。也就是说,装饰器本质就是编译时执行的函数。
//所以:这里类Person创建完成即会打印log:123
类装饰器的基本语法: 类装饰器是一个函数,可以接受一个参数,即类的构造函数。通常,类装饰器的函数名称以 @ 符号开头,并放在类声明前。示例:
// 修改类的行为,例如在类的构造函数中注入依赖。
// 定义一个装饰器工厂函数
function myDecorator(target: any, propertyKey: any) {
target.prototype.age = 13
}
// 使用装饰器工厂函数装饰类的方法
@myDecorator
class MyClass {
name:String
age:any
sex:String
constructor(value:String){
this.name = value
this.sex = "man"
}
}
const instance = new MyClass('张三');
console.log(instance.age) //13
// 定义一个依赖注入的服务
class MyDependency {
someValue: string = "Dependency Value"
}
// 定义一个类装饰器
function injectDependency(constructor: any, propertyKey: any) {
const originalConstructor = constructor
// 创建一个新构造函数,用于注入依赖
const newConstructor: any = function (...args: any[]) {
// 创建依赖实例
const dependency = new MyDependency();
// 调用原始构造函数,并传入依赖实例
return new originalConstructor(dependency, ...args);
}
// 设置新构造函数的原型链以继承原始构造函数的原型
newConstructor.prototype = originalConstructor.prototype;
return newConstructor;
}
// 使用类装饰器注入依赖
@injectDependency
class MyClass {
dependency: MyDependency;
constructor(dependency: MyDependency) {
this.dependency = dependency;
}
printDependencyValue() {
console.log(this.dependency.someValue);
}
}
let test = {
someValue:"测试"
}
// 创建 MyClass 的实例
const myInstance = new MyClass(test);
myInstance.printDependencyValue(); // 输出:Dependency Value
类装饰器的用途: 类装饰器可以用于多种用途,包括但不限于:
- 添加新属性或方法到类的原型中。
- 修改类的行为,例如在类的构造函数中注入依赖。
- 记录或监视类的创建和实例化。
- 与元数据结合使用,以提供额外的信息或配置。
装饰器工厂函数: 装饰器可以接受参数,使其更具通用性。这些参数允许您根据需要配置装饰器的行为。装饰器工厂函数返回实际的装饰器函数。
类装饰器的返回值: 类装饰器可以返回值,但它们通常不返回任何内容。如果返回一个值,它将替换原始类的构造函数。这样可以用于修改类的构造函数。
属性装饰器(Property Decorators)
属性装饰器(Property Decorators)用于修改类的属性。它允许您在属性的声明上附加元数据、修改属性的访问行为或执行其他操作。
基本语法: 属性装饰器是装饰器函数,可以附加到类的属性声明前。它接受三个参数:
- 参数1:被装饰的类的原型对象。
- 参数2:属性的名称。
- 参数3:属性的属性描述符。
属性装饰器的应用: 属性装饰器可用于执行各种任务,包括但不限于:
- 修改属性的默认值。
- 添加元数据,以便其他代码能够识别属性的附加信息。
- 在属性的
get和set方法中添加逻辑。 - 执行验证或其他业务逻辑。
//利用属性装饰器添加元数据到属性
import 'reflect-metadata'; // 确保引入 reflect-metadata 库
// 自定义属性装饰器,用于添加元数据
function addMetadata(target: any, propertyKey: any) {
const metadataKey = 'customMetadata'; // 元数据的键
const metadataValue = '要添加的元数据值'; // 要添加的元数据值
Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);
}
class MyClass {
@addMetadata
myProperty: string;
constructor(value: string) {
this.myProperty = value;
}
}
// 获取属性的元数据
const instance = new MyClass("测试");
const metadataKey = 'customMetadata';
const metadataValue = Reflect.getMetadata(metadataKey, instance, 'myProperty');
console.log(metadataValue); // 输出:SomeValue
//使用属性装饰器修改属性的默认值
function DefaultValue(value: string) {
return function(target: any, propertyName: any) {
Object.defineProperty(target, propertyName, {
value: value,
writable: true
});
}
}
class MyClass {
@DefaultValue('default')
public prop!: string;
}
let obj = new MyClass();
console.log(obj.prop); // 输出 "default"
方法装饰器(Method Decorators)
方法装饰器用于装饰类的方法。它允许您在方法的定义和执行过程中附加额外的行为、元数据或自定义逻辑。方法装饰器通常用于修改方法的行为或收集方法的元数据信息。
function methodDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
// 在方法装饰器中执行自定义逻辑
// target: 装饰器的目标对象(类的原型)
// key: 被装饰方法的名称
// descriptor: 方法的属性描述符
}
target: 装饰器的目标对象,通常是类的原型。key: 被装饰方法的名称。descriptor: 方法的属性描述符,其中包含有关方法的信息,例如方法的可配置性、可枚举性等。
方法装饰器可以用于各种用途,包括但不限于以下情况:
- 修改方法的行为:您可以在方法装饰器中修改方法的实现,添加前置或后置处理逻辑,或者完全替换方法的实现。
- 收集元数据:方法装饰器常用于收集有关方法的元数据,例如参数类型、方法参数的验证规则、访问控制等。
- 日志记录和性能分析:您可以使用方法装饰器来记录方法的执行,以进行调试或性能分析。
- 权限控制:方法装饰器可以用于实现权限控制逻辑,以确定是否允许执行方法。
//使用方法装饰器修改方法的行为
function LogMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
let originalMethod = descriptor.value; // 保存原来的方法
// 重写方法
descriptor.value = function(...args: any[]) {
console.log(`调用了 ${propertyKey} 方法,参数为:`, args.join(", "));
//将参数加2
let temple = args.map(item => item + 2)
let result = originalMethod.apply(this, temple)
console.log(`${propertyKey} 方法的结果是:`, result);
return result;
}
return descriptor;
}
class MyTestClass {
@LogMethod
sum(a: number, b: number) {
return a + b;
}
}
let obj = new MyTestClass();
console.log(obj.sum(1, 2)); // 7
参数装饰器(Parameter Decorators)
参数装饰器是 TypeScript 中的一种装饰器类型,用于装饰函数或方法的参数。它允许您在函数参数上添加元数据、自定义行为或执行额外的逻辑。参数装饰器通常用于捕获参数的元数据、验证参数值或执行前置或后置处理。 以下是参数装饰器的一般结构:
function parameterDecorator(target: any, methodName: string, parameterIndex: number) {
// 在参数装饰器中执行自定义逻辑
// target: 装饰器的目标对象(类的原型或构造函数)
// methodName: 被装饰方法的名称
// parameterIndex: 被装饰参数的索引
}
target: 装饰器的目标对象,通常是类的原型或构造函数。methodName: 被装饰参数所在方法的名称。parameterIndex: 被装饰参数的索引,从 0 开始。