Vanilla JavaScript中的事件处理程序命名空间

Tyl*_*ver 33 javascript namespaces dom-events

我熟悉jQuery事件处理程序中的命名空间.我可以在特定的命名空间中添加事件处理程序:

$('#id').on('click.namespace', _handlerFunction);
Run Code Online (Sandbox Code Playgroud)

然后我可以删除该命名空间中的所有事件处理程序:

$('#id').off('.namespace');
Run Code Online (Sandbox Code Playgroud)

这里的优点是我只能删除此命名空间中的事件,而不能删除任何应该维护的用户添加/附加事件.

有没有人有关于我如何不能使用jQuery的任何提示,但实现了类似的结果?


谢谢!!

And*_*rew 28

对于仍然在寻找这个的人,我最终制作了一个帮助单例,它跟踪我的函数引用.

class EventHandlerClass {
  constructor() {
    this.functionMap = {};
  }

  addEventListener(event, func) {
    this.functionMap[event] = func;
    document.addEventListener(event.split('.')[0], this.functionMap[event]);
  }

  removeEventListener(event) {
    document.removeEventListener(event.split('.')[0], this.functionMap[event]);
    delete this.functionMap[event];
  }
}

export const EventHandler = new EventHandlerClass();
Run Code Online (Sandbox Code Playgroud)

然后只需导入事件并使用如下:

EventHandler.addEventListener('keydown.doop', () => console.log("Doop"));
EventHandler.addEventListener('keydown.wap', () => console.log("Wap"));
EventHandler.removeEventListener('keydown.doop');
// keydown.wap is still bound
Run Code Online (Sandbox Code Playgroud)


vsy*_*ync 16

在这个解决方案中,我已经扩展了DOM on以及off能够使用事件命名空间的方法:

var events = {
  on(event, cb, opts){
    if( !this.namespaces ) // save the namespaces on the DOM element itself
      this.namespaces = {};

    this.namespaces[event] = cb;
    var options = opts || false;
    
    this.addEventListener(event.split('.')[0], cb, options);
    return this;
  },
  off(event) {
    this.removeEventListener(event.split('.')[0], this.namespaces[event]);
    delete this.namespaces[event];
    return this;
  }
}

// Extend the DOM with these above custom methods
window.on = Element.prototype.on = events.on;
window.off = Element.prototype.off = events.off;


window
  .on('mousedown.foo', ()=> console.log("namespaced event will be removed after 3s"))
  .on('mousedown.bar', ()=> console.log("event will NOT be removed"))
  .on('mousedown.baz', ()=> console.log("event will fire once"), {once: true});

// after 3 seconds remove the event with `foo` namespace
setTimeout(function(){
    window.off('mousedown.foo')
}, 3000)
Run Code Online (Sandbox Code Playgroud)
Click anywhere 
Run Code Online (Sandbox Code Playgroud)

  • 我赞成这一点,但有一些警告与在DOM中存储js对象引用有关,因为如果你不知道你在做什么,它可能导致内存泄漏.如果从DOM中删除其中一个元素,则会发生这种情况,例如,它仍会存储对事件处理程序的其他引用.如果您打算删除该元素并且一切都应该正常,请确保调用元素的"关闭"方法.我认为大多数(?)现代(?)垃圾收集器对于这个问题是明智的,但肯定有一些(尤其是较旧的)浏览器没有. (2认同)
  • @brennanyoung - 感谢upvoting,但我不明白你在说什么.这种方法不会增加新的内存危险,而这些内存危害并不存在,所以你所说的应用*used*来应用这个答案无能为力的DOM操作.请参阅[此问题](/sf/ask/184188581/). (2认同)

Wil*_* P. 10

我想你正在寻找addEventListenerremoveEventListener.您还可以使用dispatchEvent定义自定义事件并触发它们.

但是,要删除事件侦听器,您需要保留对事件函数的引用,以仅删除要删除的函数,而不是清除整个事件.

  • 这对命名空间事件有何帮助?你能举例说明如何在`window`上命名一个`mouseup`事件然后删除那个(假设还有其他非命名空间)? (13认同)