// 要使用装饰器,需要在tsconfig.json中开启 "experimentalDecorators": true, "emitDecoratorMetadata": true
// 装饰器就是给对应的类、属性、参数、方法添加前置的功能
import axios from "axios";
// 类装饰器 ClassDecorator
// 定义类装饰器,装饰器命名习惯是大写字母开头
// const Base:ClassDecorator = (target) => {
// console.log(target); // 输出的是http类的构造函数
// // 给类加装饰,对http添加属性和方法
// target.prototype.name = 'bai'
// target.prototype.fn = () => {
// console.log('fn');
// }
// }
// // 使用方式是在class上一行, @类装饰器名
// @Base
// class http {}
// const h = new http() as any
// h.fn() // fn
// console.log(h.name); // bai
import 'reflect-metadata'
// 装饰工厂,因为不能直接给dec传参,使用函数柯里化传入参数
const Base = (name:string) => {
const dec:ClassDecorator = (target) => {
// 给类加装饰,对http添加属性和方法
target.prototype.name = name
target.prototype.fn = () => {
console.log('fn');
}
}
return dec
}
// 方法装饰器
const Get = (url:string) => {
// 方法装饰器MethodDecorator,描述的类型是PropertyDescriptor
const fnDec:MethodDecorator = (target,key,descriptor:PropertyDescriptor) => {
// target是{},key是方法名getList,descriptor是获取方法的描述,descriptor.value获取函数
console.log(target,key,descriptor);
// 相当于把getList要做逻辑都写这里了,然后通过descriptor.value把请求返回的结果传给getList
axios.get(url).then(res => {
descriptor.value(res.data)
})
}
return fnDec
}
const Post = (url:string) => {
// 方法装饰器MethodDecorator,描述的类型是PropertyDescriptor
const fnDec:MethodDecorator = (target,key,descriptor:PropertyDescriptor) => {
// target是{},key是方法名getList,descriptor是获取方法的描述,descriptor.value获取函数
console.log(target,key,descriptor);
// 通过Result参数修饰器的定义的key,获取value=result
const key1 = Reflect.getMetadata('key',target)
axios.get(url).then(res => {
// 直接取res.data.result值
descriptor.value(key ? res.data[key1]:res.data)
})
}
return fnDec
}
// 参数修饰器
const Result = () => {
const fn:ParameterDecorator = (target,key,index) => {
// 使用reflect-metadata的语法
// 第一个参数是自定义的,传递给方法装饰器接收
// 第二个参数是指定要对data里的属性名,相当于value,
// 第三个是自己
Reflect.defineMetadata('key','result',target)
}
return fn
}
// 属性装饰器,意义不大,是获取属性名
const nameDeco:PropertyDecorator = (target,key) => {
// key是name
console.log(target,key)
}
// 使用装饰器的时候传入参数
@Base('bai')
class http {
@nameDeco
name: string
constructor(name:string){
this.name = name
}
@Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
getList(data:any) {
console.log(data);
}
@Post('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
postList(data:any) {
}
}
const h = new http('123') as any
h.fn() // fn
console.log(h.name); // bai