Typescript 装饰器如何用于 html 标签?

How can Typescript decorators be used for html labels?

我很难理解如何使用 Typescript decorators。我有这个代码:

class Address {
    private street: string;
    private city: string;
    private state: string;
    private zipCode: string;

    @displayName("Street")
    get streetHtml() { return this.street; }

    @displayName("City")
    get cityHtml() { return this.city; }

    @displayName("State")
    get stateHtml()  { return this.state; }

    @displayName("Zip Code")
    get zipCodeHtml() { return this.zipCode; }

    public static map(input: any) {
        let address = new Address();

        address.street = input.street;
        address.city = input.city;
        address.state = input.state;
        address.zipCode = input.zipCode;

        return address;
    }
}

function displayName(name: string) {

    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        let label: HTMLLabelElement = document.createElement('label');

        label.innerHTML = name;

        return label;
    };
}

var address = Address.map({ street: "123 My St", city: "Boise", state: "ID", zipCode: "83709" })

console.log(address.cityHtml);

然而,它唯一做的就是返回 "Boise"。我如何获得装饰器的东西?我确实在 tsconfig.

中启用了 "experimentalDecorators": true

正如@JohnWhite 所评论的那样,class return 中的 getter 是一个字符串(由编译器从 return 类型推断出来),但是装饰器是要求更改 return a HTMLLabelElement.
这可能会在编译时给您带来困难,或导致运行时错误。

话虽如此,回答你的问题:
您在装饰器中 return 不是访问器的 returned 值,因为 docs say:

If the accessor decorator returns a value, it will be used as the Property Descriptor for the member

您需要做的是更改 "Property Descriptor" 使其 return 成为您想要的值:

function displayName(name: string) {
    return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
        descriptor.get = () => {
            let label: HTMLLabelElement = document.createElement('label');
            label.innerHTML = name;

            return label;
        }
    };
}

(code in playground)


编辑

发布我的答案后,我注意到您想要获得:

<label>Boise</label>

但是你是如何尝试实现它的(以及我的回答)returns:

<label>City</label>

为了获得所需的结果,我们需要稍微更改一下我的代码:

function displayName(name: string) {
    return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
        descriptor.get = function() {
            let label: HTMLLabelElement = document.createElement('label');
            label.innerHTML = this[name.toLowerCase()];

            return label;
        }
    };
}

(code in playground)

变化在哪里:

  1. return 函数现在是常规匿名函数而不是箭头函数,因此 this 将指向 class 实例而不是 window。
  2. 内部标签 html 现在是 this[name.toLowerCase()] 而不是 name