首页 > 解决方案 > 在属性装饰器中获取属性类实例

问题描述

我正在尝试编写一个@Prop装饰器来帮助我设置自定义元素属性。

这是我试图实现的代码:

class MyClass extends HtmlElement {
   get text() {
     return this.getAttribute('text')
   }

   set text(newVal){
     this.setAttribute('text', newVal)
   }

   connectedCallback() {
     this.innerHTML = `<div>${this.text}</div>`
   }
}

这是带有装饰器的类

class MyClass extends HtmlElement {
   @Prop() text: string;

   connectedCallback() {
     this.innerHTML = `<div>${this.text}</div>`
   }
}

这是装饰器功能

const Prop = () => (target : any, key : string) => {
    const getter = () => target.getAttribute(key);
    const setter = (newVal) => target.setAttribute(key, newVal);

    if (!delete this[key]) return;
    Object.defineProperty(target, key, {
        get: getter,
        set: setter
    });
}

但是,每当调用 getter 函数时,我都会收到此错误:

Uncaught TypeError: Illegal invocation
    at HTMLElement.getter (app.js:16)

签出app.js:16显示这行代码:

const getter = () => target.getAttribute(key);

带有target.getAttribute(key);下划线。

标签: typescripttypescript-decorator

解决方案


装饰器以类作为目标而不是类的实例来调用。该类的实例将作为this. 这就是为什么在这里使用箭头函数是一个坏主意,因为它们是this从声明站点捕获的。在这种情况下,使用常规函数效果最好。

const Prop = () => (target: any, key: string, descriptor: PropertyDescriptor) => {
    const getter = function (this: HTMLElement) {
        return this.getAttribute(key);
    }
    const setter = function (this: HTMLElement, newVal) {
        this.setAttribute(key, newVal);
    }
    descriptor = descriptor || {};
    descriptor.get = getter;
    descriptor.set = setter;
    return descriptor;
}

class MyClass extends HTMLElement {
    @Prop() text: string;

    connectedCallback() {
        this.innerHTML = `<div>${this.text}</div>`
    }
}

推荐阅读