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