应移除已匹配卡片的点击事件监听器,而非禁用或隐藏;必须用具名函数绑定与移除,匹配成功后立即对两张卡片调用removeEventListener('click', handleCardClick)。

在卡片翻牌游戏(Memory Game)中,匹配成功后需要防止用户重复点击已配对的卡片,同时避免事件监听器持续触发造成逻辑混乱。关键不是“锁死卡片”本身,而是**移除已匹配卡片上的点击事件监听器**,这样它们就不再响应任何点击——这是最干净、最符合 DOM 事件机制的做法。
为什么用 removeEventListener 而不是禁用或隐藏?
禁用(disabled)对 div 无效;隐藏(display: none)会破坏布局或动画连贯性;单纯加标志位(如 isMatched)虽可行,但若监听器未被移除,仍可能因快速连点或异步延迟导致误判。而 removeEventListener 是真正切断事件源头,安全可靠。
必须使用命名函数(不能用箭头函数)
removeEventListener 要求传入与 addEventListener 完全相同的函数引用。箭头函数每次声明都是新实例,无法匹配移除。正确做法是:
- 把点击处理逻辑封装为一个具名函数(如
handleCardClick) - 绑定时用该函数名,移除时也用同一函数名
- 不要写成
card.addEventListener('click', () => { ... })
匹配成功后批量移除两张卡片的监听器
当两张卡片内容匹配,且都处于“已翻开”状态时,在判定逻辑里立即执行:
- 调用
card1.removeEventListener('click', handleCardClick) - 调用
card2.removeEventListener('click', handleCardClick) - 可选:添加
matched类名或 data 属性用于样式标识(如淡出/高亮) - 注意:确保
card1和card2是原始 DOM 元素,不是副本或 querySelectorAll 的静态列表项
避免常见陷阱
常见错误包括:
- 在循环中为每张卡片绑定监听器时,用闭包捕获索引但没保存对应元素引用 → 移除时找不到目标
- 匹配判定前未先检查是否已移除过监听器(重复调用
removeEventListener无害,但说明逻辑冗余) - 使用事件委托(如监听父容器),此时不适用
removeEventListener到单个卡片,应改用条件过滤(如if (card.classList.contains('matched')) return)


















