1.装饰器
装饰器是一种特殊的声明,可以附加到类声明、方法、属性或参数上,以修改其行为。装饰器为 TypeScript 提供了一种元编程的方式,使得你可以在编译时对类和类成员进行注解或修改。
在js中,装饰器本质是一个函数(会参与运行)
装饰器可以修饰:
- 类
- 成员(属性+方法)
- 参数
2.配置
experimentalDecorators 是 TypeScript 中的一个编译选项,用于启用实验性的装饰器特性。
{
"compilerOptions": {
"experimentalDecorators": true, // 用于启用实验性的装饰器特性。
},
}
3.类装饰器
3.1 类装饰器的使用
类装饰器的本质是一个函数,该函数接收一个参数,表示类本身,且类装饰器可以有返回值:
- void:表示仅运行函数
- 返回一个新的类:表示新的类替换掉装饰的目标
// 仅运行函数
function test(target: new () => object) {
}
@test
class A {
name: string = '测试'
}
const a: A = new A()
console.log(a.name); // 测试
// 替换装饰目标
function test(target: new () => object) {
return class B extends target {
name: string = '这是一个新的类'
}
}
@test
class A {
name: string = '测试'
}
const a: A = new A()
console.log(a.name); // 这是一个新的类
3.2 存在多个装饰器
若有多个装饰器时,则会按照装饰器的书写顺序,后加入的先调用
type Target = new () => object
function test2(target: Target) {
console.log('这是类C');
return class C {
name: string = ''
}
}
function test(target: Target) {
console.log('这是类B');
return class B extends target {
name: string = '这是一个新的类'
}
}
@test2
@test
class A {
name: string = '测试'
}
// 这是类B
// 这是类C
3.3 装饰器传递参数
通过函数返回一个装饰器,实现参数传递
type Target = new (...args: any[]) => object
function test(n: string) {
console.log(n); // 你好啊
return function (target: Target) {
return class B extends target {
name: string = '这是新类'
}
}
}
@test('你好啊')
class A { }
const a: A = new A()
4.成员装饰器
4.1 属性装饰器
属性装饰器本质是一个函数,可以传递两个参数
- 参数1
- 当修饰静态成员时,该参数为构造函数本身(类本身)
- 因为静态成员是添加在构造函数/类身上的
- 当修饰实例成员时,该参数为原型对象
- 因为实例成员是添加在原型上的
- 当修饰静态成员时,该参数为构造函数本身(类本身)
- 参数2
- 为字符串类型,固定为属性名称
function test() {
return function (target: any, n: string) {
console.log('target', target); // target {}
console.log(target == A.prototype); // true
console.log('n', n); // n name
}
}
class A {
// 修饰实例属性时
@test()
name: string = '张三'
}
function test() {
return function (target: any, n: string) {
console.log('target', target); // target [class A] { age: '12' }
console.log(target == A); // true
console.log('n', n); // n age
}
}
class A {
// 修饰静态属性时
@test()
static age: string = '12'
}
4.2 方法装饰器
方法装饰器本质是一个函数,可以接收三个参数
- 参数1
- 当修饰静态成员时,该参数为构造函数本身(类本身)
- 因为静态成员是添加在构造函数/类身上的
- 当修饰实例成员时,该参数为原型对象
- 因为实例成员是添加在原型上的
- 当修饰静态成员时,该参数为构造函数本身(类本身)
- 参数2
- 为字符串类型,固定为方法名称
- 参数3
- 方法描述,类似Object.defineProperty的属性描述
function test() {
return function (target: any, n: string, descriptor: PropertyDescriptor) {
console.log('target', target); // target {}
console.log(target == A.prototype); // true
console.log('n', n); // n getHi
console.log("descriptor", descriptor);
/**
* descriptor {
value: [Function: getHi],
writable: true,
enumerable: false,
configurable: true
}
*/
}
}
class A {
// 修饰实例成员时
@test()
getHi() { }
}
function test() {
return function (target: any, n: string, descriptor: PropertyDescriptor) {
console.log('target', target); // target [class A]
console.log(target == A); // true
console.log('n', n); // n getHi
console.log("descriptor", descriptor);
/**
* descriptor {
value: [Function: getHi],
writable: true,
enumerable: false,
configurable: true
}
*/
}
}
class A {
// 修饰静态成员时
@test()
static getHi() { }
}
5.第三方库reflect-metadata
reflect-metadata可以用于元数据存储,可以结合装饰器使用
6.第三方校验库class-validator
class-validator可以结合装饰器进行表单校验
7.第三方库class-transformer
8.第三方帖子
9.装饰器调用顺序
- 待补充