JavaScript井字棋点击事件重复触发导致计数异常问题求助
问题原因
- 核心问题是重复绑定事件监听器未清理:每次调用
newclick()时,都会给9个格子各新增1个点击监听函数,之前绑定的旧监听函数没有被移除。每次点击格子时,所有历史绑定的监听函数都会依次执行,所以计数器会多次累加,只有最后一次执行的函数修改的innerHTML会保留,所以界面看起来只新增了一个符号,和计数不匹配。 - 额外逻辑缺陷:没有判断格子是否已经被占用,已落子的格子依然可以重复触发点击事件。
解决方案
推荐采用更简洁的「单次绑定+回合/状态判断」方案,不需要反复绑定解绑事件,避免重复监听问题:
'use strict' let turn =1; // 1代表x回合,0代表o回合 let countx = 0; let counto = 0; // 存储所有格子id const cellIds = ['leftTop','centerTop','rightTop','leftCenter','centerCenter','rightCenter','leftBottom','centerBottom','rightBottom']; // 初始化:只绑定一次事件 cellIds.forEach(id => { document.getElementById(id).addEventListener('click', () => handleCellClick(id)) }) function handleCellClick(id) { const cell = document.getElementById(id); // 先判断格子是否已经落子,已落子直接返回不处理 if (cell.querySelector('p')) return; // 根据当前回合处理落子 if (turn === 1) { cell.innerHTML = '<p>x</p>'; countx++; checkWin(); turn = 0; // 切换到o回合 } else { cell.innerHTML = '<p>o</p>'; counto++; checkWin(); turn = 1; // 切换到x回合 } } function checkWin(){ if(countx==3||counto==3){ alert('you win'); } }
如果你一定要保留原有的「切换回合重新绑定事件」的逻辑,需要先把之前绑定的监听函数移除,注意不能用匿名函数,要把监听函数提取为可复用的有名函数,每次绑定前调用removeEventListener移除旧的监听即可。
内容的提问来源于stack exchange,提问作者Elay Gelbart
相关产品推荐
相关产品推荐

