JavaScript中removeEventListener移除mouse事件监听器失效问题求解
问题原因
removeEventListener 仅能移除和绑定时引用完全相同的函数,你当前代码中绑定、移除事件时使用的都是即时定义的匿名箭头函数,两次定义的匿名函数是独立的不同对象,因此移除操作不会生效。
直接修复方案
将事件处理函数提取为独立的具名函数,绑定、移除时都传入同一个函数引用即可,修改后的完整代码如下:
const p1InfP = document.getElementById('p1InfP') const tiles = document.querySelectorAll('.tile') // 提取具名事件处理函数,保证引用唯一 function handleTileMouseover(e) { e.target.style.border = "1px solid #0000FF" } function handleTileMouseout(e) { e.target.style.border = "1px solid transparent" } p1InfP.addEventListener('click', ()=> { p1InfP.style.border = "1px solid black" place(tiles) }) function place(array){ for(let i=0; i<array.length;i++){ // 绑定传入具名函数引用 array[i].addEventListener('mouseover', handleTileMouseover, true) array[i].addEventListener('mouseout', handleTileMouseout, true) } } function remove(array){ for(let i=0; i<array.length;i++){ // 移除时传入同一个具名函数引用,捕获参数和绑定时保持一致 array[i].removeEventListener('mouseover', handleTileMouseover, true) array[i].removeEventListener('mouseout', handleTileMouseout, true) } } const reset = document.getElementById('reset') reset.addEventListener('click', ()=> { p1InfP.style.border = "1px solid transparent" remove(tiles) })
注:原代码中
place/remove函数接收了array参数,但循环中直接使用了全局的tiles变量,上述代码也同步修复了这个逻辑问题。
更简单的优化方案
无需频繁绑定解绑事件,用CSS类控制样式即可实现同等效果:
- 提前在CSS中定义可放置状态的样式:
.tile.placeable:hover { border: 1px solid #0000FF !important; } .tile { border: 1px solid transparent; }
- JS逻辑简化为仅操作类名:
const p1InfP = document.getElementById('p1InfP') const tiles = document.querySelectorAll('.tile') const reset = document.getElementById('reset') p1InfP.addEventListener('click', ()=> { p1InfP.style.border = "1px solid black" tiles.forEach(tile => tile.classList.add('placeable')) }) reset.addEventListener('click', ()=> { p1InfP.style.border = "1px solid transparent" tiles.forEach(tile => tile.classList.remove('placeable')) })
这种方案代码更简洁,性能也更好,不会出现事件残留的问题。
内容的提问来源于stack exchange,提问作者phunbaba
相关产品推荐
相关产品推荐

