【问题标题】:How do I use JavaScript decorators on a class instance via Babel?如何通过 Babel 在类实例上使用 JavaScript 装饰器?
【发布时间】:2019-12-01 06:04:20
【问题描述】:

鉴于以下.babelrc 配置:

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

我无法让类装饰器工作:

@annotation
class MyClass { }

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

const c = new MyClass();
console.log(c);

另外,console.log(target) 产生以下结果:

Object [Descriptor] { kind: 'class', elements: [] }

对于console.log(c) 语句,我希望看到添加了带注释的属性,但我得到的只是MyClass {}

一些额外的说明 - 我知道 legacy: true 标志,但我希望使用现在的规范,而不使用旧的后备。我做了一些额外的研究,我认为我在正确的道路上,这里是更新的代码:

@annotation
class MyClass { }

function annotation(descriptor) {
  const {
    kind,
    elements
  } = descriptor;

  const newElements = elements.concat([{
    kind: 'field',
    placement: 'own',
    descriptor: {
      annotated: true
    }
  }]);
  return {
    kind,
    elements: newElements
  }
}

const c = new MyClass();
console.log(c);

上述方法仍然不起作用,但至少我不再遇到奇怪的错误:)

如果有兴趣,请阅读已接受答案中的 cmets 以了解一些潜在的解决方案。

** 更新 ** 我实际上设法弄清楚了 - 使用 legacy: false 选项:

@annotation
class MyClass { }

function annotation(descriptor) {
  const {
    kind,
    elements
  } = descriptor;

  const newElements = elements.concat([{
    kind: 'field',
    placement: 'own',
    key: 'annotated',
    initializer: () => true,
    descriptor: {
      configurable: true,
      writable: true,
      enumerable: true
    }
  }]);
  return {
    kind,
    elements: newElements
  }
}

const c = new MyClass();
console.log(c); // MyClass { annotated: true }

【问题讨论】:

  • 谢谢这个人,当使用这个非传统装饰器时,有没有办法像你一样将设置为 trueannotated 属性添加到 MyClass 构造函数类本身使用遗留装饰器(即不创建MyClass 的实例)?例如:console.log(MyClass.annotated); // true?另外,有没有办法区分装饰器是否与旧版和非旧版 API 一起使用?谢谢!
  • 您在哪里找到说明如何在 "legacy": false, "decoratorsBeforeExport": false 时使用 descriptor.elements 属性的规范或教程?谢谢!
  • @tonix,坦率地说,我不记得了。这很可能是某种 GH 问题/讨论,但恐怕我不能给你一个确切的链接,对此很抱歉。
  • 找到你的这篇文章:blog.fullstacktraining.com/using-decorators-in-javascript 明天去看看!还是谢谢你!
  • 哦,还有那个……(捂脸)哈哈:)

标签: javascript babeljs decorator


【解决方案1】:

返回一个在构造函数中设置属性的新类。

@annotation
class MyClass { }

function annotation(target) {
  return class extends target {
    constructor(...args) {
      super(...args);
      this.annotated = true;
    }
  }
}

const c = new MyClass();
console.log(c);

【讨论】:

  • 以上返回'Class extends value # is not a constructor or null'。
  • @Tamas 嗯...可能与不使用传统装饰器有关。较新的提案有很多错综复杂的地方。
  • @Tamas FWIW 支持该提案的人建议现在使用遗产,如果你不是一成不变的。 The decorators champion group would recommend continuing to use Babel "legacy" decorators or TypeScript "experimental" decorators.link
  • 是的,我同意你对复杂性的看法……我想我已经接近解决方案了,但它仍然不起作用。我会用更多信息更新我原来的问题
  • 我只是在试验,所以没什么大不了的,但我真的很想弄清楚如何使用新规范,legacy: false
猜你喜欢
  • 2018-04-28
  • 2019-02-03
  • 1970-01-01
  • 2015-06-24
相关资源
最近更新 更多