代码之家  ›  专栏  ›  技术社区  ›  thebjorn

通过类装饰器自动将类添加到列表中?

  •  2
  • thebjorn  · 技术社区  · 7 年前

    有可能在装饰器中获得“类对象”(构造函数)的句柄吗?

    "@date:2019-01-25" "@latlong:51.507351,-0127758"

    装饰器看起来很有前途,至少我可以将标记定义为类属性:

    function dkdatatype({tag}) {
        return function decorator(cls) {
            if (cls.kind !== 'class') throw `not class ${cls.kind}`;
    
            cls.elements.push({
                kind: 'field',
                key: 'tag',
                placement: 'static', 
                descriptor: {
                    configurable: false,
                    enumerable: true,
                    writable: false
                },
                initializer: () => tag
            });
    
            return {
                kind: 'class',
                elements: cls.elements
            };
        };
    }
    
    @dkdatatype({tag: '@date:'})
    export class DkDate extends datatype {
        constructor(...args) {
            super();
            const clstag = this.constructor.tag;
            if (typeof args[0] === 'string' && args[0].startsWith(clstag)) {
                this.value = new Date(args[0].substr(clstag.length));
            } else {
                this.value = new Date(...args);
            }
        }
        toJSON() {
            return this.constructor.tag + this.value.toISOString().slice(0, 10);
        }
    }
    

    type_registry[DkDate.tag] = DkDate
    

    但是有没有任何方法可以从装饰器(或者基类,或者其他方式)自动(并且只执行一次)执行此操作?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Jordan Running    7 年前

    根据 current proposal docs ,您想添加一个 extras finish 方法,该方法将在类完全定义后作为参数与类本身一起调用。

    下面是示例代码:

    function defineElement(tagName) {
      return function(classDescriptor) {
        let { kind, elements } = classDescriptor;
        assert(kind == "class");
        return {
          kind,
          elements,
    
          // This callback is called once the class is otherwise fully defined
          extras: [
            {
              kind: "hook",
              placement: "static",
              finish(klass) {
                window.customElements.define(tagName, klass);
              }
            }
          ]
        };
      };
    

    额外费用

    extras: [
      {
        kind: "hook",
        placement: "static",
        finish(klass) {
          type_registry[tag] = klass;
        },
      },
    ],