使用非遗留装饰器时如何装饰 JavaScript 类构造函数?



我有以下类:

@log
class Example {
constructor(name, age) {
console.log("Example constructor", name, age);
this.name = name;
this.age = age;
}
}

使用旧装饰器时,这@log装饰器:

function log(Class) {
return class extends Class {
constructor(...args) {
console.log("log", args);
super(...args);
}
};
}
// .babelrc
// ...
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
// ...
]
// ...

上面的设置运行良好,以下代码:

const example = new Example("Graham", 34);

输出:

log (2) ["Graham", 34]
Example constructor Graham 34

现在,当我使用非传统装饰器时,我如何获得相同的结果,即:

// .babelrc
// ...
"plugins": [
[
"@babel/plugin-proposal-decorators",
{ "decoratorsBeforeExport": false }
],
// ...
]
// ...

如何实现@log使其以与传统装饰器相同的方式工作?

function log(...args) {
const [descriptor] = args;
const { kind, elements } = descriptor;
const newElements = elements.concat({
kind: "method",
placement: "prototype",
key: "constructor",
descriptor: {
value: (...args) => {
// I have tried this but it doesn't work...
console.log("log", args);
},
configurable: true,
writable: true,
enumerable: true,
},
});
return {
kind,
elements: newElements,
};
}

我已经尝试了上面的代码,但它不起作用。问题是在使用非遗留装饰器时我没有对目标的引用。您知道是否有办法实现与传统行为相同的行为吗?

谢谢。

我已经找到了答案,感谢 BabelJS Slack 频道上的 loganfsmyth。

你必须返回一个对象,其中包含一个名为finisher包装类的属性,例如:

function log(...args) {
const [descriptor] = args;
const { kind, elements } = descriptor;
return {
kind,
elements,
finisher: (Class) => {
return class extends Class {
constructor(...args) {
console.log("log", args);
super(...args);
}
};
}
};
}

然后,使用非旧版装饰器时,此代码:

@log
class Example {
constructor(name, age) {
console.log("Example constructor", name, age);
this.name = name;
this.age = age;
}
}
const example = new Example("Graham", 34);

输出:

log (2) ["Graham", 34]
Example constructor Graham 34

与传统装饰器一样。

很难找到答案,因为非遗留装饰器的这个功能没有记录在@babel/插件提案装饰器上。

最新更新