-
Metadata Value {Any} (后文简写 v)。元数据的类型,任意类型都行。
-
Target {Object} (后文简写 o)。表示要在这个对象上面添加元数据
-
Property {String|Symbol} (后文简写 p)。用于设置在哪个属性上添加元数据。大家可能会想,这个是干什么用的,不是可以在对象上面添加元数据了么?其实不仅仅可以在对象上面添加元数据,甚至还可以在对象的属性上面添加元数据。其实大家可以这样理解,当你给一个对象定义元数据的时候,相当于你是默认指定了 undefined 作为 Property。
了解了这 4 个概念,我们阅读对应的 API 就会比较容易。
API设计
最为全面的 API 可以查阅标准文档: https://rbuckton.github.io/reflect-metadata/
API 的设计也是非常清晰明了,metadata 毕竟也属于 “数据”,那么对应的 API 就是跟数据库的 CURD 增删改查的操作相对应的。
先罗列一下完整的 API 声明,然后我们在挨个拆分讲解:
namespace Reflect {
// 用于装饰器
metadata(k, v): (target, property?) => void
// 在对象上面定义元数据
defineMetadata(k, v, o, p?): void
// 是否存在元数据
hasMetadata(k, o, p?): boolean
hasOwnMetadata(k, o, p?): boolean
// 获取元数据
getMetadata(k, o, p?): any
getOwnMetadata(k, o, p?): any
// 获取所有元数据的 Key
getMetadataKeys(o, p?): any[]
getOwnMetadataKeys(o, p?): any[]
// 删除元数据
deleteMetadata(k, o, p?): boolean
}
▐ 创建元数据**(Reflect.metadata/Reflect.defineMetadata)**
两种方式创建,其最本质都是调用源码中 OrdinaryDefineOwnMetadata 方法,所以结果是一样的,只是使用方式不一样。
一种是通过装饰器声明方式创建,推荐的方式,也是很主流的一种方式:
// 装饰类
@Reflect.metadata(key, value)
class Example {
}
// 装饰静态属性
class Example {
@Reflect.metadata(key, value)
static staticProperty;
}
// 装饰实例属性
class Example {
@Reflect.metadata(key, value)
property;
}
// 装饰静态方法
class Example {
@Reflect.metadata(key, value)
static staticMethod() { }
}
// 装饰实例方法
class Example {
@Reflect.metadata(key, value)
method() { }
}
另一种就是 “事后”(类创建完后)再给目标对象创建元数据:
class Example {
// property declarations are not part of ES6, though they are valid in TypeScript:
// static staticProperty;
// property;
constructor§ { }
static staticMethod§ { }
method§ { }
}
// 给 类本身 加元数据
Reflect.defineMetadata(“custom:annotation”, options, Example);
// 给 类的静态属性 新增元数据
Reflect.defineMetadata(“custom:annotation”, options, Example, “staticProperty”);
// 给 类的实例属性 新增元数据,注意是加在 prototype 上
Reflect.defineMetadata(“custom:annotation”, options, Example.prototype, “property”);
// 给 类的静态方法 新增元数据
Reflect.defi