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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21817397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 21:44:40  来源:igfitidea点击:

Event Handler Namespace in Vanilla JavaScript

javascriptnamespacesdom-events

提问by Tyler Conover

I'm familiar with namespaces in jQuery's event handlers. I can add an event handler in a specific namespace:

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

$('#id').on('click.namespace', _handlerFunction);

And then I can remove all event handlers in that namespace:

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

$('#id').off('.namespace');

The advantage here is that I can remove only the events in this namespace, not any user-added/additional events that should be maintained.

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

Does anyone have any tips on how I can not use jQuery, but achieve a similar result?

有没有人对我如何不能使用 jQuery,但达到类似的结果有任何提示?

采纳答案by Will P.

I think you are looking for addEventListenerand removeEventListener. You can also define custom events and fire them using dispatchEvent.

我认为您正在寻找addEventListenerremoveEventListener。您还可以定义自定义事件并使用dispatchEvent触发它们。

However, to remove an event listener, you will need to retain a reference to the event function to remove just the function you want to remove instead of clearing the whole event.

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

回答by Andrew

For anyone still looking for this, I ended up making a helper singleton which keeps track of the function references for me.

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

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();

Then just import EventHandler and use like:

然后只需导入 EventHandler 并使用:

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

回答by vsync

In this solution I've extended the DOM to have onand offmethods with the ability to use events namespacing:

在这个解决方案我已经延长了DOM有onoff与使用事件的命名空间的能力的方法:

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)
Click anywhere