装饰器 Decorator
它是一项实验性特性,在未来的版本中可能会发生改变
它们不仅增加了代码的可读性,清晰地表达了意图,而且提供一种方便的手段,增加或修改类的功能
启用实验性的装饰器特性,必须在命令行或tsconfig.json
里启用编译器选项
1 2 3 4 5 6 7
| {
"experimentalDecorators": true, "emitDecoratorMetadata": true,
}
|
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。
学习点
- 类装饰器:
ClassDecorator
- 方法装饰器:
MethodDecorator
- 属性装饰器:
PropertyDecorator
- 参数装饰器:
ParameterDecorator
- 装饰器工厂
类装饰器
定义一个类装饰器函数 他会把Http
的构造函数传入你的Base
函数当做第一个参数,注意是构造函数不是原型
优势:当原先的类有很多业务代码,无法全部理清,但是又需要添加新的方法或属性。因为迭代器返回的是构造函数,可以在回调方法中加入你所需要的业务,这是不影响原先业务
1 2 3 4 5 6 7 8 9 10 11 12 13
| const Base:ClassDecorator=(target)=>{ console.log(target) target.prototype.Name='hale'; target.prototype.fn=()=>{ console.log('本人单身') } } @Base class Http { } const http=new Http() as any; http.fn() console.log(http.Name)
|
方法装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import axios from 'axios'; const Get = (url: string) => { const fn: MethodDecorator = (target, key, descriptor: PropertyDescriptor) => { console.log(target, key, descriptor)
axios.get(url).then(res => { descriptor.value(res.data) }) } return fn }
class Http { @Get('https://api.apiopen.top/api/getUserInfoForId/1') getList(data: any) { console.log(data)
} }
const http = new Http()
|
装饰器工厂
其实也就是一个高阶函数 外层的函数接受值,里层的函数最终接受类的构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const Base = (params: string) => { const fn: ClassDecorator = (target:Function) => { console.log(target) console.log(params) target.prototype.Name = 'hale'; target.prototype.getFn = () => { console.log('本人单身') } } return fn }
@Base('张三') class Http {
} const http=new Http() as any; http.fn() console.log(http.Name)
|
参数装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import axios from 'axios'; import 'reflect-metadata' const Get = (url: string) => { const fn: MethodDecorator = (target, key, descriptor: PropertyDescriptor) => { const metadata=Reflect.getMetadata('key',target); console.log(metadata) axios.get(url).then(res => { descriptor.value(metadata?res[metadata]:res) }) } return fn } const Result = () => { const fn: ParameterDecorator = (target, propertyKey, parameterIndex) => {
Reflect.defineMetadata('key', 'data', target) } return fn } class Http { @Get('https://api.apiopen.top/api/getUserInfoForId/1') getList( @Result() data: any) { console.log(data)
} }
const http = new Http()
|
参数装饰器的优先级大于方法装饰器
属性装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const Name: PropertyDecorator = (target, propertyKey)=>{
console.log(target, propertyKey) } class Http { @Name name: string constructor() { this.name = '张三' } }
|