您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

TypeScript Reflect Metadata

本节介绍的 Reflect data 主要用来在声明的时候和读取元数据。通过这种方式给对象额外的信息,是不会影响对象的结构的。

Reflect,翻译为『反射』,data,翻译为『元数据』。反射这个概念在 Java 等众多语言中已经广泛运用,Reflect data 就是通过装饰器来给类一些的信息,然后通过反射将这些信息出来,也可以通过反射来这些信息。

通过 npm 安装这个库:

npm i reflect-data --save

而且需要在 tscon.json 中配置:

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true,
    "emitDecoratordata": true
  }
}

命令行使用:

tsc --target ES5 --experimentalDecorators --emitDecoratordata

当启用后,只要 reflect-data 库被引入了,设计阶段的类型信息可以在运行时使用。

import 'reflect-data'

@Reflect.data('token', 'aW1vb2M=')
class Employee {

  @Reflect.data('level', 'D2')
  salary() {
    console.log('这是个秘密')
  }

  @Reflect.data('times', 'daily')
  static meeting() {}

}

const token = Reflect.getdata('token', Employee)
const level = Reflect.getdata('level', new Employee(), 'salary')
const times = Reflect.getdata('times', Employee, 'meeting')

console.log(token) // aW1vb2M=
console.log(level) // D2
console.log(times) // daily

TIPS: 注意, 实例与静态取元数据是不同的,实例需要在类的实例上取元数据,静态直接在类上取元数据。

import 'reflect-data'
 
// 元数据的命令式定义,定义对象或的元数据
Reflect.definedata(dataKey, dataValue, target)
Reflect.definedata(dataKey, dataValue, target, propertyKey)
 
// 检查对象或的原型链上是否存在元数据键
let result = Reflect.hasdata(dataKey, target)
let result = Reflect.hasdata(dataKey, target, propertyKey)
 
// 检查对象或是否存在自己的元数据键
let result = Reflect.hasdata(dataKey, target)
let result = Reflect.hasdata(dataKey, target, propertyKey)
 
// 对象或原型链上元数据键的元数据值
let result = Reflect.getdata(dataKey, target)
let result = Reflect.getdata(dataKey, target, propertyKey)
 
// 对象或的自己的元数据键的元数据值
let result = Reflect.getOwndata(dataKey, target)
let result = Reflect.getOwndata(dataKey, target, propertyKey)
 
// 对象或原型链上的所有元数据键
let result = Reflect.getdataKeys(target)
let result = Reflect.getdataKeys(target, propertyKey)
 
// 对象或的所有自己的元数据键
let result = Reflect.getOwndataKeys(target)
let result = Reflect.getOwndataKeys(target, propertyKey)
 
// 从对象或中元数据
let result = Reflect.deletedata(dataKey, target)
let result = Reflect.deletedata(dataKey, target, propertyKey)
 
// 通过装饰器将元数据应用于构造
@Reflect.data(dataKey, dataValue)
class C {
  // 通过装饰器将元数据应用于()
  @Reflect.data(dataKey, dataValue)
  method() {
  }
}

Reflect data 结合上节介绍的装饰器:

import 'reflect-data'

function get(path: string): MethodDecorator {
  return (target, name) => {
    Reflect.definedata('path', path, target, name)
  }
}

class Employee {
  @get('/init')
  async init() {}
}

const data = Reflect.getdata('path', new Employee(), 'init')
console.log(data) // '/init'

解释: 如果经常开发 Node.js 的同学对这样的写法是不是有些熟悉呢?类 init() 上的装饰器 get() 传入元数据 '/init',再通过反射拿到这个路由信息,将这些路由信息进行一定的封装,然后绑定在 koa-router 上,就能达到加载路由的。

本节介绍了 Reflect data 的一些基础使用方式,一些基础库源码如 vue-class-componentAngular 均使用了 Reflect data ,有兴趣的可以深入源码学习下。


联系我
置顶