在addEventListener时为具名函数传递参数,同时还能移除它

4,218 阅读2分钟

  泡面最近在做一个基于Vue的组件,之间要用到通过addEventListener绑定鼠标事件,但遇到一个问题。就是 需要在绑定匿名函数时候传递参数,当然,这个很容易,但是当你要动态移除掉这个匿名函数时就很麻烦了。那有没有一种我即不使用匿名函数也能传递参数,这样我就能很方便的在后期使用removeEventListener移除掉它。当然有!

问题

有如下代码:

// bind event
element.addEventListener('click', _bindEventHandler)
// unbind event
element.removeEventListener('click', _bindEventHandler)

我如果在使用具名函数传递参数呢? 当然可以这样:

element.addEventListener('click', function() {
  _bindEventHandler(param1, param2)
})

问题,分析与解决

但,这样有个问题就是,我如果再想同步的移除该绑定事件,那就无法移除了,因为没有函数名称,我们在移除的时候无法直接进行通过removeEventListener进行移除。 So,泡面这里想到了一个曲线救国的办法,那就是将参数直接绑定在element上,因为我们在使用具名函数时,addEventListener会静默将事件的event传递给函数。因此当我们再想找回这些参数,我们就可以直接通过event.target来获取。

// 设置参数
element._params = { param1, param2 }
// 绑定事件
element.addEventListener('click', _bindEventHandler)
// 在函数中获取参数
function _bindEventHandler(event) {
  const params = event.target._params
  // ...do sth after
}

OK,这样我们就实现了参数的传递, 同时也可以很方便的移除绑定事件了! 是不是很开心?

one more thing

有个问题,当我绑定的element事件遇到事件委托时,就需要额外处理一下。例如我们在绑定一个有层级结构的按钮或者DOM时, 当点击内部的DOM,我们会无法获取到在实际绑定事件的DOM上设置的参数。 这里我们就需要通过遍历事件绑定的对象来获取参数了。

我们可以通过event.path(event.composedPath())来获取Dom上的参数