反射装饰器不保存/检索对象

时间:2016-08-21 16:54:22

标签: javascript typescript

我做错了什么?我有以下装饰器函数设置来保存关于类的元数据,它们都看起来像这样(一个用于设置数据,另一个用于获取数据):

function setComponentMenu(text: string): any {
    return Reflect.metadata('componentPath', text);
}
function getMenuPath(target: any): any {
    return Reflect.getMetadata('componentPath', target);
}

然后我就这样使用了它,customEditor装饰工作得很好,并将CameraEditor类的实例放入Globals.editors

@customEditor(Camera)
@setComponentMenu('Renderers/Camera')
class CameraEditor extends Editor {

}

在设置了值之后,我尝试将其恢复为:

for(let i = 0; i < Globals.editors.length; i++){
    let editor: Editor = Globals.editors[i];
    let path = getMenuPath(editor);
    console.log(path);
}

我收到了undefined,这对于没有@setComponentMenuCameraEditor确实拥有它的项目很好,所以我希望控制台显示{{1} }。

有什么问题?

1 个答案:

答案 0 :(得分:1)

类装饰器需要具有以下签名:

function decorator(constructor: Function)

如果要将值传递给它,则需要使用decorator factory

function setComponentMenu(text: string) {
    return (constructor) => {
        ...
    }
}

此外,您不应将class decorator的值返回为:

  

如果类装饰器返回一个值,它将替换该类   使用提供的构造函数声明。

     

注意如果您选择返回新的构造函数,则必须   注意保持原始原型。适用的逻辑   运行时的装饰器不会为你做这个。

除非您想要替换构造函数。

我无法使用Reflect.metadata使其工作,但我使用Reflect.defineMetadata想出了一个有效的解决方案:

function setComponentMenu(text: string) {
    return (constructor) => {
        Reflect.defineMetadata("componentPath", text, constructor, "class");
    }
}

function getMenuPath(target: any): any {
    return Reflect.getMetadata("componentPath", target.constructor, "class");
}

您可以将元数据信息保存到原型而不是构造函数:

function setComponentMenu(text: string) {
    return (constructor) => {
        Reflect.defineMetadata("componentPath", text, constructor.prototype, "class");
    }
}

function getMenuPath(target: any): any {
    return Reflect.getMetadata("componentPath", target.constructor.prototype, "class");
}