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

  泡面最近在做一个基于Vue的组件,之间要用到通过addEventListener绑定鼠标事件,但遇到一个比较恶心的问题。就是
需要在绑定匿名函数时候传递参数,当然,这个很容易,但是当你要动态移除掉这个匿名函数时就很麻烦了。

起因

有如下代码:

1
2
3
4
// bind event
element.addEventListener('click', _bindEventHandler)
// unbind event
element.removeEventListener('click', _bindEventHandler)

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

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

分析与解决

但,这样有个问题就是,我如果再想同步的移除该绑定事件,那就无法移除了,因为没有函数名称,我们在移除的时候无法直接进行通过

1
2
3
4
5
6
7
8
9
10
11
12
So,泡面这里想到了一个曲线救国的办法,那就是将参数直接绑定在```element```上,因为我们在使用具名函数时,```addEventListener```会静默将事件的```event```传递给函数。因此当我们再想找回这些参数,我们就可以直接通过```event.target```来获取。

```javascript
// 设置参数
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上的参数