首页 > 解决方案 > 使用参数承载函数添加和删除事件侦听器

问题描述

好吧,第一次在这里发帖。几天来,我一直在查看有关此问题的帖子,但找不到解决方法。

我有一个具有唯一 ID 的图像矩阵(基本上排列的球体)。我想为所述领域添加不同的功能。所以我继续添加事件监听器。到目前为止一切都很好。触发第一个事件后,我希望所有球体都更改其事件侦听器,因此我继续删除所有事件侦听器并添加新事件侦听器。我无法删除事件侦听器。

添加事件:

for (let i = 0; i < 11; i++) {
    for (let j = 0; j < 11; j++) {
        if ((i > 1 && i < 9 && j > 1 && j < 9) && checkCorners(i, j) === true) {
            let ball = document.getElementById(i.toString() + j.toString());
            ball.addEventListener('click', removeBall(i, j));
        }
    }
}

removeBall():

var removeBall = function(i, j) {
    return function curried_func(ii, jj) {
        let ball = document.getElementById(i.toString() + j.toString());
        ball.src = "./public/assets/ball_empty.png";
    }
}

我正在使用 curried 函数方法,因为它是我尝试过的最后一种方法,除了从 e (事件)参数中检索对象数据之外,由于 e 未定义,这似乎不起作用。或使用处理程序。或者使用绑定。

删除事件:

for (let i = 0; i < 11; i++) {
    for (let j = 0; j < 11; j++) {
        if ((i > 1 && i < 9 && j > 1 && j < 9) && checkCorners(i, j) === true) {
            let ball = document.getElementById(i.toString() + j.toString());
            // ball.somethingToRevmoveEvent?
        }
    }
}

我确实觉得有必要提到它也是我的第一个 javascript 严肃项目,所以如果有人有更好的解决方案或解决方法(而不是为功能添加和删除事件 100 次),请分享。

矩阵供参考 - 用户应移除 1 个球,此时该点变为黑色,然后任何球都可以跳过另一个球以填充空白点(“跳过的球”被移除)。我认为这是某种中国跳棋谜题。

标签: javascript

解决方案


虽然柯里化很好,但它意味着每次调用它都会返回一个新函数,而不是同一个函数的副本。您需要以某种方式保存对正在绑定的函数的引用,然后在删除事件侦听器时使用它。如果没有其余代码的上下文,我将尝试在下面对其进行伪编码:

const eventMap = new Map();

function getMapKey(i, j) {
    return `${i},${j}`;
}

function addEvents() {
    for (let i = 0; i < 11; i++) {
        for (let j = 0; j < 11; j++) {
            if ((i > 1 && i < 9 && j > 1 && j < 9) && checkCorners(i, j) === true) {
                let ball = document.getElementById(i.toString() + j.toString());
                let removeBallFn = removeBall(i, j);
                let key = getMapKey(i, j);
                eventMap.set(key) = removeBallFn;
                ball.addEventListener('click', removeBallFn);
            }
        }
    }
}

function removeEvents() {
    for (let i = 0; i < 11; i++) {
        for (let j = 0; j < 11; j++) {
            if ((i > 1 && i < 9 && j > 1 && j < 9) && checkCorners(i, j) === true) {
                let ball = document.getElementById(i.toString() + j.toString());
                let key = getMapKey(i, j);
                let removeBallFn = eventMap.get(key) = removeBallFn;
                ball.removeEventListener('click', removeBallFn);
                eventMap.delete(key);
            }
        }
    }
}

这是未经测试的,因为我没有你的其余代码。原理是,每次我们生成一个“删除”函数时,我们使用一个唯一键将其存储在Map( eventMaphere) 中,该键基于循环中该点的i和值的连接。j然后,当我们要删除时,使用相同的键将相同的“删除”函数从地图中拉出,并将其传递给removeEventListener. 还有其他方法可以做到这一点——这只是一种选择。考虑到代码的更大上下文,根据需要进行调整。希望这对你有用!


推荐阅读