Appearance
reflect-metadata
是一个 JavaScript 库,用于在运行时访问和操作装饰器的元数据。它提供了一组 API,可以读取和写入装饰器相关的元数据信息。
我们可以将 类 上一些数据进行收集,收集后进行标记。让器具备模型特定自定义属性
- class 装饰target 是构造函数
- 静态属性,则为类本身;如果是实例属性,则为类的原型
- 如果是静态方法,则为类本身;如果是实例方法,则为类的原型
下面用到 Reflect.metadata
他的本质其实是
ts
function metadata(metadataKey,metadataValue){
return function(target,key){
Reflect.defineMetadata(metadataKey, metadataValue, target, key);
}
}
正因如此 Reflect.getMetadata
是获取原型链上的 绑定的因此通过 对象也可以直接获取内容,相对class 装饰器则需要构造函数因为 他的target 并不是原型链
ts
import "reflect-metadata";
@Reflect.metadata("class", "classValue")
class A {
@Reflect.metadata("property", "propertyValue")
name: string;
@Reflect.metadata("method", "methodValue")
getName() {
return this.name;
}
}
const a = new A();
const classValue = Reflect.getMetadata("class", A);
console.log(`Class metadata value: ${classValue}`);
const propertyValue = Reflect.getMetadata("property", a, "name");
console.log(`Property metadata value: ${propertyValue}`);
const methodValue = Reflect.getMetadata("method", a, "getName");
console.log(`Method metadata value: ${methodValue}`);
const classValue1 = Reflect.getMetadata("class", a.constructor);
console.log(`Class metadata value: ${classValue1}`);
const propertyValue1 = Reflect.getMetadata("property", a, "name");
console.log(`Property metadata value: ${propertyValue1}`);
const methodValue1 = Reflect.getMetadata("method", a, "getName");
console.log(`Method metadata value: ${methodValue1}`);
// Class metadata value: classValue
// Property metadata value: propertyValue
// Method metadata value: methodValue
// Class metadata value: classValue
// Property metadata value: propertyValue
// Method metadata value: methodValue
但如果都想获取原型链的可以进行适当自定义封装的装饰
ts emitDecoratorMetadata
在ts 还帮你自动收集 一些其他信息需要你开启 emitDecoratorMetadata
design:type
:用于属性的类型元数据。design:paramtypes
:用于构造函数或方法参数的类型元数据。design:returntype
:用于方法的返回类型元数据
ts
import 'reflect-metadata';
// 类装饰器
function classDecorator(target: any) {
}
// 参数装饰器
function paramDecorator(target: any, propertyKey: string, parameterIndex: number) {
}
// 属性装饰器
function propDecorator(target: any, propertyKey: string) {
}
// 方法装饰器
function methodDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
}
@classDecorator
class Example {
@propDecorator
myProperty: string;
constructor(@paramDecorator serviceA: string, @paramDecorator serviceB: string) {
console.log('Example instance created');
}
@methodDecorator
myMethod(): string {
return 'hello';
}
}
// 获取属性的类型元数据
const propertyType = Reflect.getMetadata('design:type', Example.prototype, 'myProperty');
console.log('Property type:', propertyType.name);
const paramTypes = Reflect.getMetadata('design:paramtypes', Example);
console.log('Constructor param types:', paramTypes.map((type: any) => type.name));
const returnType = Reflect.getMetadata('design:returntype', Example.prototype, 'myMethod');
console.log('Method return type:', returnType.name);
案例
js
const formatMetadataKey = Symbol("format");
function format(formatString: string) {
return Reflect.metadata(formatMetadataKey, formatString);
}
function getFormat(target: any, propertyKey: string) {
return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
}
class Greeter {
@format("Hello, %s")
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
let formatString = getFormat(this, "greeting");
return formatString.replace("%s", this.greeting);
}
}
const objG = new Greeter("world");
// console.log(objG.greet()); // "Hello, world"
const objG = new Greeter("world");
// console.log(objG.greet());
// greet封装在外面也是一样的道理
function greet(obj: any, key: string) {
let formatString = getFormat(obj, key);
return formatString.replace("%s", obj[key]);
}
const g = greet(objG, "greeting");
console.log(g);