TypeScript | 装饰器(@)

装饰器(Decorators)是TypeScript的一种特殊类型的声明,用于在不修改原始代码的情况下增强代码功能,它能够被附加到类声明方法属性或者参数上。

  • 语法:它以@符号为前缀,后跟一个表达式,通常是一个函数。
  • 常见的装饰器有: 类装饰器属性装饰器方法装饰器参数装饰器
    (1)类装饰器,它的参数是类的构造函数。
    (2)属性装饰器,它的参数是类的原型对象和属性名。
    (3)方法装饰器,它的参数是类的原型对象、方法名和方法的属性描述符。
    (4)参数装饰器,它的参数是类的原型对象、方法名和参数的索引。
  • 装饰器的写法: 分为普通装饰器(无法传参)装饰器工厂(可以传参)

举一个普通装饰器的例子:

function TestClass(target: any) {
  target.name = 'test';
  target.age = '10';
}

// 定义一个装饰器函数TestClass,名字随便起
@TestClass
class PersonClass {
  // ...
}

console.log(PersonClass.name);  // 输出:test
console.log(PersonClass.age);       // 输出:10

在上述代码中,@TestClass便是一个装饰器,它在PersonClass 类被实例化的时候会执行,此时控制台会打印出相关日志。

举一个装饰器工厂的例子:

// 利用函数柯里化解决传参问题, 向装饰器传入一些参数,也可以叫参数注解
function TestClass(newValue: string) {
  return function(target: any) {
    // 这个 value 就是外界传递进来的参数,添加到实例的 prototype 上
    target.prototype.name = newValue;
    target.prototype.age = 10;
  }
}

// 在使用装饰器时传递元数据
@TestClass('newTest')
class PersonClass {
  // ...
}

const person = new PersonClass();
console.log(person.name); // 输出:newTest
console.log(person.age);      // 输出:10

1、类装饰器
类装饰器是应用于类声明的装饰器。它会在类声明时调用,并接收类的构造函数作为参数。类装饰器通常用于修改或扩展类的行为。

function TestClass(target: any) {
  target.xx = 'PersonClass'; // 给类增加属性
  target.prototype.name = 'test';
  target.prototype.age = '10';
}

@TestClass
class PersonClass {
  // ...
}

let person = new PersonClass();
console.log(person.age); // 输出:10

2、属性装饰器
属性装饰器是用于类属性的装饰器。它可以用于修改类属性的元数据或进行其他的操作,但不能直接修改属性的值。属性装饰器接收两个参数:
target:类的原型对象,指向该属性所在的类的原型。
propertyKey:属性的名称。
属性装饰器通常用于修改或监视属性的行为。

function TestClass(target: any, propertyKey: string) {
  console.log(target); // PersonClass{}
  console.log("key " + propertyKey); // key name
};

class PersonClass {
  @TestClass
  name: string;
  
  constructor() {
    this.name = 'test';
  }
}

const person = new PersonClass();
person.name = '你好!'
console.log(person.name) // 你好!

3、方法装饰器
方法装饰器是应用于类方法的装饰器,可以对方法的行为进行增强或修改。方法装饰器接收三个参数:
target:类的原型对象,指向该方法所在的类的原型。
propertyKey:方法的名称。
descriptor:方法的描述符,它是 Object.getOwnPropertyDescriptor(target, propertyKey) 返回的对象,包含方法的元数据。你可以修改这个描述符,改变方法的行为。

function TestClass(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
   const originalMethod = descriptor.value;
   descriptor.value = function (...args: any[]) {
	  console.log("Method: ", propertyKey);
	  return originalMethod.apply(this, args);
  };
}

class PersonClass {
  @TestClass
  greet(name: string) {
    return `Hello, ${name}!`;
  }
}

const person = new PersonClass();
person.greet("AA"); // 输出:Method: TestClass
                      // 输出:Hello, AA!

4、参数装饰器
参数装饰器是应用于类方法参数的装饰器。它可以在方法执行之前或之后对方法的参数进行某种处理。参数装饰器通常用于依赖注入、日志记录、验证等场景。
target: 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
propertyKey: 方法的名称
parameterIndex: 参数在函数参数列表中的索引

function TestClass(target: any, propertyKey: string | symbol, parameterIndex: number) {
  console.log(`Class at index ${parameterIndex} in method ${String(propertyKey)} is decorated.`);
}

class PersonClass {
  greet(@TestClass name: string) {
    console.log(`Hello, ${name}!`);
  }
}

const person = new PersonClass();
person.greet("AA");
// 输出:
// Class at index 0 in method greet is decorated.
// Hello, AA!

装饰器组合
在TypeScript中,我们可以将多个装饰器组合在一起使用。装饰器组合的顺序是从下至上的顺序(自下而上)依次执行。

function TestClass(target: any) {
  console.log(`Class:`, target);
}

function TestTwoClass(target: any) {
  console.log(`TwoClass:`, target);
}

class PersonClass {
  @TestClass
  @TestTwoClass
  greet(name: string) {
    console.log(`Hello, ${name}!`);
  }
}

const person = new PersonClass();
person.greet("AA");  // 会先执行 TestTwoClass,然后 TestClass

TypeScript 项目开启装饰器
tsconfig.json 文件中,有一个叫 experimentalDecorators 的属性,你需要将其设置为 true,才能在 TypeScript 中启用装饰器。

{
    "compilerOptions": {
        "target": "es6", // 表示输出的 JavaScript 代码符合 ES6 标准。
    	"module": "esnext",
        "experimentalDecorators": true, // 表示启用装饰器。
        "emitDecoratorMetadata": true, // 表示额外生成装饰器的元数据,在某些情况下使用装饰器时,这是必须的。
        "strict": true  // 可选,开启严格模式以获得更强的类型检查
    }
}

参考文章
TypeScript 入门教程

以上是本次分享全部内容。
非常感谢您阅读本篇博客文章。希望这篇文章能够为您提供有价值的信息,并帮助您解决问题或增长知识。如果您对文章内容有任何问题、建议或反馈。同时,也欢迎您继续关注我的博客,获取更多有趣、实用的内容。
期待与您在下一篇文章再次见面。谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值