removeEventListener 没有从窗口中删除事件

离开我的草坪

我创建了两个装饰器,一个附加到一个方法,该方法在对象上创建一个属性,并将一个函数附加到该对象,以便稍后添加到事件侦听器中。

StackBlitz 示例

它看起来像这样:

export const EVENT_BINDING_PREFIX = '__attachEventBinding_'

export function Event(listenerLocation: string) {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    return Object.defineProperty(target, `${EVENT_BINDING_PREFIX}${propertyKey}`, {
      configurable: true,
      value: {
        type: 'event',
        name: listenerLocation.split(':'),
        binding: descriptor.value
      }
    })
  }
}

接下来,我有一个扩展它所附加到的对象的绑定。当对象被实例化时,它会添加从上述函数创建的绑定。

export function GameObject(options?: object) {
  return function <T extends { new(...args: any[]): object }>(constructor: T) {
    return class extends constructor {
      constructor(...args: any[]) {
        super(...args)
        this.addBindings()
      }

      get bindings() {
        return Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(this)))
          .filter(i => i.startsWith(EVENT_BINDING_PREFIX))
          .map(b => (this as any)[b] as EventBinding)
      }

      addBindings() {
        this.bindings.forEach(binding => {
          const [nodeOrEvent, event] = binding.name
          if (nodeOrEvent === 'window' && event.length > 0) {
            window.addEventListener(event, binding.binding.bind(this))
          }
        })
      }

      removeBindings() {
        this.bindings.forEach(binding => {
          const [nodeOrEvent, event] = binding.name
          if (nodeOrEvent === 'window' && event) {
            window.removeEventListener(event, binding.binding.bind(this))
          }
        })
      }
    }
  }
}

当我调用时.removeBindings(),函数运行window.removeEventListener但是,绑定实际上永远不会从窗口中删除。是什么导致这种情况发生?

以下是所有这些的调用方式:

@GameObject({})
class Player {
  @AddEvent('window:click')
  windowClick() {
    console.log('here');
  }
}

const player = new Player();
setTimeout(() => {
  (player as any).removeBindings();
}, 5000);
某些表演

每次.bind执行函数时,都会创建一个新函数。

removeEventListener仅当处理程序与===传递给的处理程序相同 ( )时才有效addEventListener

function foo() {}
const bound1 = foo.bind();
const bound2 = foo.bind();

// not the same
console.log(bound1 === bound2);

您需要保存对绑定函数的引用,类似于

type AddedBindings = { eventName: string, fn: (...args: unknown[]) => unknown }[];
export function GameObject(options?: object) {
    return function <T extends { new(...args: any[]): object }>(constructor: T) {
      return class extends constructor {
        private addedBindings: AddedBindings = [];
addBindings() {
  const addedBindings: AddedBindings = [];
  this.bindings.forEach(binding => {
    const [nodeOrEvent, eventName] = binding.name
    if (nodeOrEvent === 'window' && eventName.length > 0) {
      const fn = binding.binding.bind(this);
      addedBindings.push({ eventName, fn });
      window.addEventListener(eventName, fn)
    }
  });
  this.addedBindings = addedBindings;
}

removeBindings() {
  this.addedBindings.forEach(({ eventName, fn }) => {
    window.removeEventListener(eventName, fn);
  });
}

另一个可能简化类型的选项是持久保存删除绑定函数,而不是将事件名称和处理程序保存在属性中。

addBindings() {
    const addedBindings = this.bindings
        .filter(({ name: [nodeOrEvent, eventName] }) => nodeOrEvent === 'window' && eventName.length > 0)
        .map((binding) => {
            const fn = binding.binding.bind(this);
            const eventName = binding[1];
            window.addEventListener(eventName, fn)
            return { eventName, fn };
        });
    this.removeAllBindings = () => {
        for (const { eventName, fn } of addedBindings) {
            window.removeEventListener(eventName, fn);
        }
    };
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

我如何使用React useEffect窗口removeEventListener

Javascript“ removeEventListener”没有对匿名函数做任何事情,没有简单的方法吗?

document.body.removeEventListener不适用于删除按键事件的侦听器

当事件处理程序是原型函数时,如何使用removeEventListener?

从窗口中删除事件处理程序功能?

当删除附加的DOM节点(如removeEventListener事件)时,是否应该删除/断开MutationObservers?

用户调整窗口大小时的RemoveEventListener

document.body.removeEventListener删除所有单击事件侦听器(不是指定的函数)为什么?

为什么这个react / javascript“ removeEventListener”不能删除监听器?

问题与document.removeEventListener()

removeEventListener未删除

带有回调功能的代码覆盖率istanbuljs,例如removeEventListener中

removeEventListener不会删除keydown上的事件

用于类中“滚动”事件的removeEventListener

如何删除eventListener。removeEventListener不起作用

为什么使用removeEventListener而不是仅仅删除它?

无法通过removeEventListener删除EventListener

RemoveEventListener不删除事件

具有命名函数的window.removeEventListener无法正常工作

是否有必要在每个 addEventListener 之前 removeEventListener?

在Javascript中删除事件侦听器表单元素无需克隆元素并且不知道removeEventListener()的第二个参数

模拟 removeEventListener ionic 3

无法从函数调用 removeEventListener

React removeEventListener 未被删除

removeEventListener 没有按预期工作

js 事件处理程序使用 removeEventListener 运行一次

调用 removeEventListener 后滚动事件仍然有效

窗口关闭事件,不在没有窗口管理器的窗口中运行?

setInterval 中的 removeEventListener