1. 解释
Reflect,翻译为『反射』,Metadata,翻译为『元数据』。反射这个概念在 Java 等众多语言中已经广泛运用,Reflect Metadata 就是通过装饰器来给类添加一些自定义的信息,然后通过反射将这些信息提取出来,也可以通过反射来添加这些信息。
2. 安装使用
npm i reflect-metadata --save
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}}
tsc --target ES5 --experimentalDecorators --emitDecoratorMetadata
当启用后,只要 reflect-metadata
库被引入了,设计阶段添加的类型信息可以在运行时使用。
import 'reflect-metadata'@Reflect.metadata('token', 'aW1vb2M=')class Employee {
@Reflect.metadata('level', 'D2')
salary() {
console.log('这是个秘密')
}
@Reflect.metadata('times', 'daily')
static meeting() {}}const token = Reflect.getMetadata('token', Employee)const level = Reflect.getMetadata('level', new Employee(), 'salary')const times = Reflect.getMetadata('times', Employee, 'meeting')console.log(token) console.log(level) console.log(times)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
TIPS: 注意, 实例方法与静态方法取元数据是不同的,实例方法需要在类的实例上取元数据,静态方法直接在类上取元数据。
3. API
import 'reflect-metadata'
Reflect.defineMetadata(metadataKey, metadataValue, target)Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey)
let result = Reflect.hasMetadata(metadataKey, target)let result = Reflect.hasMetadata(metadataKey, target, propertyKey)
let result = Reflect.hasMetadata(metadataKey, target)let result = Reflect.hasMetadata(metadataKey, target, propertyKey)
let result = Reflect.getMetadata(metadataKey, target)let result = Reflect.getMetadata(metadataKey, target, propertyKey)
let result = Reflect.getOwnMetadata(metadataKey, target)let result = Reflect.getOwnMetadata(metadataKey, target, propertyKey)
let result = Reflect.getMetadataKeys(target)let result = Reflect.getMetadataKeys(target, propertyKey)
let result = Reflect.getOwnMetadataKeys(target)let result = Reflect.getOwnMetadataKeys(target, propertyKey)
let result = Reflect.deleteMetadata(metadataKey, target)let result = Reflect.deleteMetadata(metadataKey, target, propertyKey)
@Reflect.metadata(metadataKey, metadataValue)class C {
@Reflect.metadata(metadataKey, metadataValue)
method() {
}}
- 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
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
4. 结合装饰器使用
Reflect Metadata 结合上节介绍的装饰器:
import 'reflect-metadata'function get(path: string): MethodDecorator {
return (target, name) => {
Reflect.defineMetadata('path', path, target, name)
}}class Employee {
@get('/init')
async init() {}}const metadata = Reflect.getMetadata('path', new Employee(), 'init')console.log(metadata)
解释: 如果经常开发 Node.js 的同学对这样的写法是不是有些熟悉呢?类方法 init()
上的装饰器 get()
传入元数据 '/init'
,再通过反射拿到这个路由信息,将这些路由信息进行一定的封装,然后绑定在 koa-router
上,就能达到自动加载路由的功能。
5. 小结
本节介绍了 Reflect Metadata 的一些基础使用方式,一些基础库源码如 vue-class-component
、Angular
均使用了 Reflect Metadata ,有兴趣的可以深入源码学习下。