我做错了什么?我设置了以下装饰器函数来保存有关类的元数据,它们看起来都是这样的(一个用于设置数据,一个用于获取数据):
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);
}
我得到了未定义
,这对于没有@setComponentMenu
但CameraEditor
有它的项目来说很好,所以我期望控制台显示Renderers/Camera
。
出了什么问题?
最佳答案
类装饰器需要具有以下签名:
function decorator(constructor: Function)
如果你想向它传递值,那么你需要使用 decorator factory :
function setComponentMenu(text: string) {
return (constructor) => {
...
}
}
此外,您不应该为 class decorator 返回值如:
If the class decorator returns a value, it will replace the class declaration with the provided constructor function.
NOTE Should you chose to return a new constructor function, you must take care to maintain the original prototype. The logic that applies decorators at runtime will not do this for you.
当然除非你想替换构造函数。
我无法使用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");
}
您可以将元数据信息保存到原型(prototype)而不是构造函数中:
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");
}
关于javascript - 反射装饰器不保存/检索对象的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39066616/