首页 > 解决方案 > Javascript 装饰器监听器

问题描述

我正在和装饰器混在一起,有一个 Angular 背景,我正试图将我的头包裹在HostListener装饰器周围。

这是我走了多远:

class Demo {
        counter = 0;

        @Listen("mousemove") onMouseMove(e?) {
            console.log(this);

            this.counter++;
        }
    }

    export function Listen(name) {
        return (target, key, descriptor) => {

            window.addEventListener(name, oldValue.bind(target));


            return descriptor;
        };
    }

    new Demo();

这或多或少是实现唯一的问题是传递目标/此引用,因为目标未初始化。

标签: javascriptdecorator

解决方案


解决了,我正在使用 Vue,所以这可能不是每个人的答案,基本上我正在做的是在 Vue 中调用该函数一次,您可以添加一个 mixin,并且在这个 mixinbeforeMount中将调用钩子,从而允许我在这里调用一次。

装饰器更新代码:

export function Listen(name) {
    return function (target, key, descriptor) {
        if (!target.subscriptions) target.subscriptions = [];


        add(target, "Listen", key);

        if (process.client) {
            const oldValue = descriptor.value;

            descriptor.value = function() {
                target.subscriptions.push(
                    target.$eventManager.add(window, name, oldValue.bind(this))
                );
            };

            return descriptor;
        }

        return descriptor;
    };
}

const add = (target, name, functionName) => {
    if(!target.decorators) target.decorators = {};
    if(!target.decorators[name]) target.decorators[name] = [];

    target.decorators[name].push(functionName);
};

Vue 混合:

Vue.mixin({
    beforeMount: function() {
        if(this.decorators && this.decorators.Listen) {
            this.decorators.Listen.forEach(key => this[key]());
        }
    },
    destroyed: function () {
        this.$subscriptionManager.remove(this.subscriptions);
    }
});

推荐阅读