Vanilla JavaScript 中的事件处理程序命名空间
Posted
技术标签:
【中文标题】Vanilla JavaScript 中的事件处理程序命名空间【英文标题】:Event Handler Namespace in Vanilla JavaScript 【发布时间】:2014-03-16 01:25:33 【问题描述】:我熟悉 jQuery 事件处理程序中的命名空间。我可以在特定命名空间中添加事件处理程序:
$('#id').on('click.namespace', _handlerFunction);
然后我可以删除该命名空间中的所有事件处理程序:
$('#id').off('.namespace');
这里的好处是我只能删除这个命名空间中的事件,而不是任何应该维护的用户添加/附加事件。
有没有人有任何关于我如何不能使用 jQuery,但获得类似结果的提示?
【问题讨论】:
danml.com/js/events.js 有这样的东西:您可以使用正则表达式进行选择。还可以在 bower 和 microjs 中搜索“事件”以获取更多类似的内容... 相关:Namespaced Custom Events Trigger 【参考方案1】:对于仍在寻找这个的人,我最终制作了一个助手单例,它为我跟踪函数引用。
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();
然后只需导入 EventHandler 并使用如下:
EventHandler.addEventListener('keydown.doop', () => console.log("Doop"));
EventHandler.addEventListener('keydown.wap', () => console.log("Wap"));
EventHandler.removeEventListener('keydown.doop');
// keydown.wap is still bound
【讨论】:
美丽在于简单 +1 非常好!保存回调函数的引用是个好主意。 是的。我喜欢这个。最干净的 @MaxCore 是的,developer.mozilla.org/en-US/docs/Web/API/Event/Event 如果您添加一个具有相同签名的事件而不删除先验,您将失去对前一个的引用,该项目将有两个事件,但有一个绑定引用。您需要更好地控制functionMap
。【参考方案2】:
在这个解决方案中,我将 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)
Click anywhere
【讨论】:
我对此表示赞同,但在 DOM 中存储 js 对象引用有一些注意事项,因为如果你不知道自己在做什么,它可能会导致内存泄漏。例如,如果您从 DOM 中删除其中一个元素,而它仍然存储对事件处理程序的附加引用,则可能会发生这种情况。如果您打算删除该元素,请确保调用元素的“关闭”方法,一切都应该很好。我认为大多数(?)现代(?)垃圾收集器对这个问题是明智的,但肯定有一些(尤其是旧的)浏览器不是。 相关:addEventListener-memory-leaks【参考方案3】:我认为您正在寻找addEventListener 和removeEventListener。您还可以定义自定义事件并使用dispatchEvent 触发它们。
但是,要删除事件侦听器,您需要保留对事件函数的引用,以便仅删除要删除的函数,而不是清除整个事件。
【讨论】:
有道理。我非常专注于将事件处理程序与命名空间一起放置,我没有检查 removeEventListener 上的文档。谢谢。 这对事件命名空间有何帮助?你能举例说明如何在window
上命名mouseup
事件,然后只删除那个事件(假设还有其他非命名空间)?
但是如果我没有对要删除EventListener 的函数的引用怎么办?命名空间在 jQuery 中非常方便。
@vsync 在下面看到我的答案。以上是关于Vanilla JavaScript 中的事件处理程序命名空间的主要内容,如果未能解决你的问题,请参考以下文章
当弹出窗口关闭时,我将如何引发事件(jQuery 或 vanilla Javascript)?
使用 vanilla JavaScript 在客户端处理 Firebase ID 令牌
es6 vanilla javascript中的Ajax请求
javascript [相同]用于匹配数组#vanilla #script中的两个字符串的脚本