简体   繁体   English

无法使用代理捕获 customElements 上的访问器调用?

[英]Unable to trap accessor calls on customElements using Proxy?

I'm registering some custom elements using customElements.define and would like to automatically set up traps on member accessors so that I can emit events when they change我正在使用 customElements.define 注册一些自定义元素,并希望在成员访问器上自动设置陷阱,以便在它们更改时发出事件

class State extends HTMLElement {
    public someValue = 1;

    public constructor() {
        super();
        console.log('State constructor');
    }
}

const oProxy = new Proxy(State, {
    get(target, prop: string) {
        console.log(`GET trap ${prop}`);
        return Reflect.get(target, prop);
    },
    set(target, prop: string, value: any) {
        console.log(`SET trap ${prop}`);
        return Reflect.set(target, prop, value);
    }
});

customElements.define('my-state', oProxy);

const oStateEl = document.querySelector('my-state');
console.log(oStateEl.someValue);
console.log(oStateEl.someValue = 2);
console.log(oStateEl.someValue);

My browser doesn't seem to have a problem with the above code and I can see some trap output as the element is set up我的浏览器似乎对上述代码没有问题,并且在设置元素时我可以看到一些陷阱 output

GET trap prototype
GET trap disabledFeatures
GET trap formAssociated
GET trap prototype

But when I manually get/set values the traps aren't triggered.但是当我手动获取/设置值时,不会触发陷阱。 Is this even possible?这甚至可能吗?

What I ended up doing was moving all member variable values to a private object and dynamically defining a getter/setter for each as soon as the custom element was mounted on the DOM like so...我最终做的是将所有成员变量值移动到私有 object 并在自定义元素安装在 DOM 上后立即为每个变量动态定义一个 getter/setter,就像这样......

//
class State extends HTMLElement {

    protected _data: object = {}

    public connectedCallback() {
        // Loop over member vars
        Object.getOwnPropertyNames(this).forEach(sPropertyKey => {
            // Ignore private
            if(sPropertyKey.startsWith('_')) {
                return;
            }

            // Copy member var to data object
            Reflect.set(this._data, sPropertyKey, Reflect.get(this, sPropertyKey));

            // Remove member var
            Reflect.deleteProperty(this, sPropertyKey);

            // Define getter/setter to access data object
            Object.defineProperty(this, sPropertyKey, {
                set: function(mValue: any) {
                    console.log(`setting ${sPropertyKey}`);
                    Reflect.set(this._data, sPropertyKey, mValue);
                },

                get: function() {
                    return this._data[sPropertyKey];
                }
            });
        });
    }

}

// 
class SubState extends State {

    public foobar = 'foobar_val';
    public flipflop = 'flipflop_val';

    public SubStateMethod() { }

}

//
window.customElements.define('sub-state', SubState);

//
const oState = document.querySelector('sub-state') as SubState;
oState.foobar = 'foobar_new_val';

That way I can still get/set values on the object as normal, typescript is happy that the member variables exist, and I can trigger custom events when members are accessed - all while allowing custom elements to exist within the markup at DOM ready这样我仍然可以像往常一样在 object 上获取/设置值,typescript 很高兴成员变量存在,并且我可以在访问成员时触发自定义事件 - 同时允许自定义元素存在于 DOM 就绪的标记中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM