Appearance
装饰器Decorator
Decorator 装饰器是一项实验性特性,在未来的版本中可能会发生改变 它们不仅增加了代码的可读性,清晰地表达了意图,而且提供一种方便的手段,增加或修改类的功能
开启功能
若要启用实验性的装饰器特性,你必须在命令行或 tsconfig.json 里启用编译器选项
json
"experimentalDecorators": true,
"emitDecoratorMetadata": true,类装饰器 ClassDecorator
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。
首先定义一个类
ts
class A {
constructor() {
}
}定义一个类装饰器函数 他会把 ClassA 的构造函数传入你的 watcher 函数当做第一个参数
ts
const watcher: ClassDecorator = (target: Function) => {
target.prototype.getParams = <T>(params: T): T => {
return params
}
}TIP
ClassDecorator 是类装饰器
target 是构造函数
使用的时候,直接通过 @函数名使用
ts
@watcher
class A {
constructor() {
}
}验证
ts
const a = new A();
console.log((a as any).getParams('123'));装饰器工厂
其实也就是一个高阶函数,外层的函数接受值,里层的函数最终接受类的构造函数
ts
const watcher = (name: string): ClassDecorator => {
return (target: Function) => {
target.prototype.getParams = <T>(params: T): T => {
return params
}
target.prototype.getOptions = (): string => {
return name
}
}
}
@watcher('name')
class A {
constructor() {
}
}
const a = new A();
console.log((a as any).getParams('123'));装饰器组合
就是可以使用多个装饰器
ts
const watcher = (name: string): ClassDecorator => {
return (target: Function) => {
target.prototype.getParams = <T>(params: T): T => {
return params
}
target.prototype.getOptions = (): string => {
return name
}
}
}
const watcher2 = (name: string): ClassDecorator => {
return (target: Function) => {
target.prototype.getNames = (): string => {
return name
}
}
}
@watcher2('name2')
@watcher('name')
class A {
constructor() {
}
}
const a = new A();
console.log((a as any).getOptions());
console.log((a as any).getNames());属性装饰器 PropertyDecorator
返回两个参数
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 属性的名字。
[ {}, 'name', undefined ]
ts
const met: PropertyDecorator = (...args) => {
console.log(args);
}
class A {
@met
name: string
constructor() {
}
}
const a = new A();方法装饰器 MethodDecorator & PropertyDescriptor
返回三个参数
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
示例
- target
{}, - propertyKey
'getList', - descriptor
{ value: [Function:getList], writable: true, enumerable:false, configurable:true }
ts
import axios from "axios";
const Get = (url: string): MethodDecorator => {
return (target, propertyKey, descriptor: PropertyDescriptor) => {
console.log(target, propertyKey, descriptor)
axios.get(url).then(res => {
descriptor.value(res)
})
}
}
class A {
constructor() {
}
@Get('https://v.api.aa1.cn/api/yiyan/index.php')
getList(data: any) {
console.log('data', data)
}
create() {
}
}
const a = new A();TIP
ts-node 编译必须使用 CommonJS 模式,否则报错
参数装饰器 ParameterDecorator
返回三个参数
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 参数在函数参数列表中的索引。
示例:
target
propertyKey
parameterIndex
[{}, 'setParasm', 0]ts
import axios from "axios";
const Get = (url: string): MethodDecorator => {
return (target, propertyKey, descriptor: PropertyDescriptor) => {
console.log(target, propertyKey, descriptor)
axios.get(url).then(res => {
descriptor.value(res)
})
}
}
const Result = (): ParameterDecorator => {
return (target, propertyKey, parameterIndex) => {
console.log(target, propertyKey, parameterIndex)
}
}
class A {
constructor() {
}
@Get('https://v.api.aa1.cn/api/yiyan/index.php')
//getList(data: any) { //
getList(@Result() data: any) {
console.log('data', data)
}
create() {
}
}
const a = new A();元数据存储
ts
import 'reflect-metadata'可以快速存储元数据然后在用到的地方取出来 defineMetadata getMetadata
ts
import axios from "axios";
const Get = (url: string): MethodDecorator => {
return (target, propertyKey, descriptor: PropertyDescriptor) => {
console.log(target, propertyKey, descriptor)
const key = Reflect.getMetadata('key', target)
axios.get(url).then(res => {
descriptor.value(res)
})
}
}
const Result = (): ParameterDecorator => {
return (target, propertyKey, parameterIndex) => {
console.log(target, propertyKey, parameterIndex)
Reflect.defineMetadata('key', 'animal', target)
// 中间的关键字,写什么就是存什么,'animal'就是数据中的一个
}
}
class A {
constructor() {
}
@Get('https://zj.v.api.aa1.cn/api/Age-calculation/?birthday=2000-01-01')
//getList(data: any) {
getList(@Result() data: any) {
console.log('data', data)
}
create() {
}
}
const a = new A();