【问题标题】:Automatically adding a class to a list through a class decorator?通过类装饰器自动将类添加到列表中?
【发布时间】:2019-01-25 20:15:41
【问题描述】:

是否可以在装饰器中获取“类对象”(构造函数)的句柄?

背景:我想用带有类型标记的字符串值解析 json'ish 格式,例如"@date:2019-01-25""@latlong:51.507351,-0127758"

这是对旧 js 库的现代化改造,通过覆盖子类化和实例创建来实现。

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

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

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

【问题讨论】:

    标签: javascript decorator


    【解决方案1】:

    根据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 看起来像这样:

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-25
    • 2013-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-15
    • 2012-04-11
    • 1970-01-01
    相关资源
    最近更新 更多