Skip to main content

@babel/plugin-proposal-decorators

示例

¥Example

简单类装饰器

¥Simple class decorator

JavaScript
@annotation
class MyClass {}

function annotation(target) {
target.annotated = true;
}

类装饰器

¥Class decorator

JavaScript
@isTestable(true)
class MyClass {}

function isTestable(value) {
return function decorator(target) {
target.isTestable = value;
};
}

类方法装饰器

¥Class method decorator

JavaScript
class C {
message = "hello!";

@bound
m() {
console.log(this.message);
}
}

function bound(value, { name, addInitializer }) {
addInitializer(function () {
this[name] = this[name].bind(this);
});
}

安装

¥Installation

npm install --save-dev @babel/plugin-proposal-decorators

用法

¥Usage

¥With a configuration file (Recommended)

babel.config.json
{
"plugins": [
["@babel/plugin-proposal-decorators", { "version": "2023-11" }]
]
}

通过 Node API

¥Via Node API

JavaScript
require("@babel/core").transformSync("code", {
plugins: [
["@babel/plugin-proposal-decorators", { version: "2023-11" }],
]
});

选项

¥Options

History
版本变化
v7.24.0添加了对 version: "2023-11" 的支持
v7.22.0添加了对 version: "2023-05" 的支持
v7.21.0添加了对 version: "2023-01" 的支持
v7.19.0添加了对 version: "2022-03" 的支持
v7.17.0添加了 version 选项,支持 "2021-12""2018-09""legacy"

version

"2023-11""2023-05""2023-01""2022-03""2021-12""2018-09""legacy"

¥"2023-11", "2023-05", "2023-01", "2022-03", "2021-12", "2018-09" or "legacy".

选择要使用的装饰器提案:

¥Selects the decorators proposal to use:

提醒

Babel 8 仅支持 "2023-11""legacy"。如果你使用不同的装饰器版本,建议迁移到 "2023-11"

¥Babel 8 will only support "2023-11" and "legacy". If you are using a different decorators version, it's recommended to migrate to "2023-11".

spec repo 提供了一个简短的 这些版本之间差异的总结

¥The spec repo provides a brief summary of the differences between these versions.

如果指定 decoratorsBeforeExport 选项,则 version 默认为 "2018-09",否则为必需选项。

¥If you specify the decoratorsBeforeExport option, version defaults to "2018-09", otherwise it is a required option.

decoratorsBeforeExport

这个选项:

¥This option:

  • 使用 version: "legacy"version: "2022-03"version: "2023-01"version: "2023-05"version: "2023-11" 时不允许;

    ¥is disallowed when using version: "legacy", version: "2022-03", version: "2023-01", version: "2023-05" or version: "2023-11";

  • 使用 version: "2018-09" 时需要;

    ¥is required when using version: "2018-09";

  • 是可选的,使用 version: "2021-12" 时默认为 false

    ¥is optional and defaults to false when using version: "2021-12".

boolean

JavaScript
// decoratorsBeforeExport: false
export @decorator class Bar {}

// decoratorsBeforeExport: true
@decorator
export class Foo {}

添加此选项最初是为了帮助 tc39 通过允许对建议的语法进行实验来收集社区的反馈。该提案现在决定在 export 之前或之后允许装饰器。

¥This option was originally added to help tc39 collect feedback from the community by allowing experimentation with the proposed syntaxes. The proposal has now settled on allowing decorators either before or after export.

legacy

弃用

请改用 version: "legacy"。此选项是旧别名。

¥Use version: "legacy" instead. This option is a legacy alias.

boolean,默认为 false

¥boolean, defaults to false.

使用旧版(阶段 1)装饰器的语法和行为。

¥Use the legacy (stage 1) decorators syntax and behavior.

注意:与 @babel/plugin-transform-class-properties 的兼容性

¥NOTE: Compatibility with @babel/plugin-transform-class-properties

如果你手动包含插件并使用类元素转换,例如

¥If you are including your plugins manually and using class elements transforms such as

  • @babel/plugin-transform-class-properties

  • @babel/plugin-transform-private-methods

  • @babel/plugin-transform-private-property-in-object

  • @babel/plugin-transform-class-static-block

确保 @babel/plugin-proposal-decorators 位于它们之前。

¥make sure that @babel/plugin-proposal-decorators comes before them.

babel.config.json
{
"plugins": [
- "@babel/plugin-transform-class-properties",
["@babel/plugin-proposal-decorators", { "version": "2023-11" }]
+ "@babel/plugin-transform-class-properties"
]
}

如果你已经在使用 @babel/preset-env 和 Stage 3 装饰器,你可以安全地删除类元素转换,Babel 会在任何预设之前自动应用装饰器转换:

¥If you are already using @babel/preset-env and Stage 3 decorators, you can safely remove the class elements transform, Babel will automatically apply decorators transform before any presets:

babel.config.json
{
"presets": [
["@babel/preset-env"],
],
"plugins": [
- "@babel/plugin-transform-class-properties",
["@babel/plugin-proposal-decorators", { "version": "2023-11" }]
]
}

如果你使用 @babel/preset-env 和旧版装饰器,则必须确保启用类元素转换,无论你的目标是什么,因为 Babel 仅支持在编译类属性时编译旧版装饰器:

¥If you are using @babel/preset-env and legacy decorators, you must ensure the class elements transform is enabled regardless of your targets, because Babel only supports compiling legacy decorators when also compiling class properties:

babel.config.json
{
"presets": [
["@babel/preset-env", {
+ "include": [
+ "@babel/plugin-transform-class-properties"
+ ]
}],
],
"plugins": [
- "@babel/plugin-transform-class-properties",
["@babel/plugin-proposal-decorators", { "version": "legacy" }]
]
}

include 选项将启用 @babel/preset-env 中包含的转换,以便你可以安全地将它们从 package.json 中删除。

¥The include option will enable the transforms included in @babel/preset-env so you can safely remove them from your package.json.

提示

你可以阅读有关配置插件选项 此处 的更多信息

¥You can read more about configuring plugin options here

Symbol.metadata 说明

¥Symbol.metadata notes

当使用装饰器访问或修改装饰器上下文中的元数据时,你需要使用 Symbol.metadata。当 Symbol.metadata 不可用时,Babel 默认使用 Symbol.for("Symbol.metadata"):这可能与使用不同后备的其他软件包不兼容。

¥When using decorators which either access or modify the metadata in the decorator context, you need to use Symbol.metadata. When Symbol.metadata is not available, Babel defaults to Symbol.for("Symbol.metadata"): this may be incompatible with other packages that use a different fallback.

为了确保 Symbol.metadata 全局可用,并且在转译过程中与 Babel 装饰器插件使用的符号匹配,你需要包含一个定义它的 polyfill,或者自行定义它:

¥To ensure that Symbol.metadata is available globally and matches the symbol used by the Babel decorators plugin during transpilation, you will need to either include a polyfill that defines it, or define it yourself:

symbol-metadata-polyfill.js
Symbol.metadata = Symbol.for("Symbol.metadata");

你也可以使用第三方 polyfill,例如 core-js/proposals/decorator-metadata-v2.js。确保在任何使用装饰器或访问 Symbol.metadata 的代码之前执行 polyfill。

¥You can also use a third-party polyfill, such as core-js/proposals/decorator-metadata-v2.js. Make sure that the polyfill is executed before any code that uses decorators or accesses Symbol.metadata.

参考

¥References