JavaScript调用removeEventListener移除点击事件不生效如何解决?
问题根因
- 作用域冲突:你把
clickHandler函数定义在了setSquare函数内部,属于局部作用域变量,全局作用域下的clickDone函数无法访问到这个函数引用,调用removeEventListener时传入的clickHandler实际是未定义值,自然无法匹配到已绑定的事件,移除失败。 - 逻辑不符合需求:你的原有逻辑是点击任意td后就移除所有td的点击事件,这根本实现不了「再次点击移除绿色背景」的需求,事件移除后后续点击不会有任何响应。
优化方案
你完全不需要动态添加/移除事件,只需要在点击事件里判断当前td的背景状态做切换即可,修改后的JS代码如下:
window.onload = initAll; var images = [ 'assets/abe.svg', 'assets/and.svg', 'assets/bjorn.svg', 'assets/boffel.svg', 'assets/pingvin.svg', 'assets/solove.svg', 'assets/elefant.svg', 'assets/elg.svg', 'assets/flamingo.svg', 'assets/flodhest.svg', 'assets/fugl.svg', 'assets/faar.svg', 'assets/ged.svg', 'assets/guldfisk.svg', 'assets/haj.svg', 'assets/hane.svg', 'assets/hest.svg', 'assets/hjort.svg', 'assets/hone.svg', 'assets/hund.svg', 'assets/kaenguru.svg', 'assets/kakadue.svg', 'assets/kamel.svg', 'assets/kanin.svg', 'assets/kat.svg', 'assets/ko.svg', 'assets/lama.svg', 'assets/lemur.svg', 'assets/marsvin.svg', 'assets/mus.svg', 'assets/nasehorn.svg', 'assets/papegoje.svg', 'assets/love.svg', 'assets/struds.svg', 'assets/rotte.svg', 'assets/skildpadde.svg', 'assets/svin.svg', 'assets/zebra.svg' ]; // init: 给#reload绑定刷新事件,初始化第一版宾果卡 function initAll() { if (document.getElementById) { document.getElementById("reload").onclick = setSquare; setSquare(); } else { alert("你的浏览器不支持该脚本。"); } } // 从图片数组随机选18张填充到宾果卡格子 function setSquare() { var randomArray = getRandom(images, 18); for (var i = 0; i < 18; i++) { document.getElementById("square" + i).src = randomArray[i]; } // 绑定点击事件,直接切换背景 document.querySelectorAll('td:not(#free)').forEach(e => { // 先移除之前可能绑定的事件,避免重置卡片时重复绑定 e.removeEventListener("click", toggleBg); e.addEventListener("click", toggleBg); }); } // 切换td背景的处理函数 function toggleBg() { this.style.background = this.style.background === "green" ? "" : "green"; } // 从指定数组中取出n个不重复的随机元素 function getRandom(arr, n) { var result = new Array(n), len = arr.length, taken = new Array(len); if (n > len) throw new RangeError("getRandom: 取出的元素数量超过数组可用长度"); while (n--) { var x = Math.floor(Math.random() * len); result[n] = arr[x in taken ? taken[x] : x]; taken[x] = --len in taken ? taken[len] : len; } return result; }
额外优化提示
你的HTML中多个td使用了相同的id="free",id属性在单页中必须唯一,建议改成class="free",对应的选择器改成td:not(.free)即可。
内容的提问来源于stack exchange,提问作者Sign644g
相关产品推荐
相关产品推荐

