Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在addEventListener中将参数传递给外部函数_Javascript_Addeventlistener - Fatal编程技术网

Javascript 如何在addEventListener中将参数传递给外部函数

Javascript 如何在addEventListener中将参数传递给外部函数,javascript,addeventlistener,Javascript,Addeventlistener,好的,这个问题在网上已经有很多答案了,我已经阅读了所有的答案,我认为没有一个适合我的情况。经过两个小时的努力,我决定放弃,并询问这里的人们: 这是一个简化的示例:我有一个函数,它将由一个按钮点击触发,我将调用它click,它带有一个参数。在click函数中,我需要使用addEventListener()向窗口对象添加事件侦听器 我需要将事件传递给handleKeydown(),因为我需要知道是否按下了shift键(keycode==16),并且我需要将参数map传递给handleKeydown(

好的,这个问题在网上已经有很多答案了,我已经阅读了所有的答案,我认为没有一个适合我的情况。经过两个小时的努力,我决定放弃,并询问这里的人们:

这是一个简化的示例:我有一个函数,它将由一个按钮点击触发,我将调用它click,它带有一个参数。在click函数中,我需要使用
addEventListener()
向窗口对象添加事件侦听器

我需要将事件传递给
handleKeydown()
,因为我需要知道是否按下了shift键
(keycode==16)
,并且我需要将参数
map
传递给
handleKeydown()
,因为我需要对它做些什么。之后,会有更多的事情要做,比如说它有在地图上画画的功能

所以我写了下面的代码:

function click (map) { // can be called multiple times, so multiple listener are attached, not needed

    this.addEventListener("keydown", function(e) {handleKeydown(e, map)}, false)
    drawPictureOnMap(map);
}

function deletePictureOnMap() { 
    // user always call this function to delete the picture before they
    // call the click() to draw a new one

    // delete the picture on map
}

function handleKeydown(e, map) {
    if (e.keyCode == 16) {
        // do something to map, e. g.:
        // map.getLayers()
    }
}
它工作正常,直到今天,我发现它有一个大问题。

因为函数click可以被多次调用,所以我发现多个事件侦听器被附加到窗口对象。这对性能有负面影响

其思想是将
removeEventlistener()
附加到另一个函数,这意味着删除地图上的图片因为用户总是在绘制新图片之前删除图片。

问题是,我无法使用匿名函数删除事件侦听器。但是如果我想使用外部函数,我找不到方法将map参数传递给它。


另一个想法是,将map参数设置为全局,这样我就不需要将其传递给handleKeydown。但是我不愿意这样做。

有几种方法可以解决这个问题。在没有更多信息的情况下,我们想到的是:为给定元素维护处理程序的
WeakMap
(一个
WeakMap
,这样,如果元素被删除并且对它的所有引用都被删除,映射条目就会自动被删除)。甚至IE11也支持
WeakMap
(无论如何,已经足够了)

在元素到处理程序映射中,存储由
map
键控的处理程序的
map

然后在
中单击
,使用这些地图:

function click (map) { // can be called multiple times, so multiple listener are attached, not needed
    let handlers = elementClickHandlers.get(this);
    if (!handlers) {
        handlers = new Map();
        elementClickHandlers.set(this, handlers);
    }
    let handler = handlers.get(map);
    if (!handler) {
        handler = function(e) {handleKeydown(e, map)};
        handlers.set(map, handler);
    }
    this.addEventListener("keydown", handler, false)
    drawPictureOnMap(map);
}
删除时,找到元素和映射的处理程序并删除:

const handlers = elementClickHandlers.get(theElement);
if (handlers) {
    const handler = handlers.get(map);
    if (handler) {
        handlers.delete(map);
        someElement.removeEventListener("click", handler, false);
    }
}

但是如果你展示了一个合适的解决方案,我们可能会建议有更简单的方法来解决问题。

请用一个演示问题的例子来更新你的问题,最好是使用堆栈片段(
[]
工具栏按钮;)来运行问题。对不起,真正的项目与openlayers相关,问题的最小可运行时间将导致大约300行。但关键点仅与addEventListener和removeEventListener相关。所以我只能这样来说明这个问题@T.J.CrowderNo,您可以创建一个仅包含
addEventListener
/
removeEventListener
方面的MCVE,足以回答问题。你可以选择不这样做,这使得人们更难帮助你。但你可以做到。我不确定我是否完全理解你的问题,但我还是建议你阅读(希望能有所帮助):
const handlers = elementClickHandlers.get(theElement);
if (handlers) {
    const handler = handlers.get(map);
    if (handler) {
        handlers.delete(map);
        someElement.removeEventListener("click", handler, false);
    }
}