开发井字棋游戏时无法为被点击的div元素添加class的问题
问题原因与解决方案
你写的事件绑定逻辑本身是符合JS事件机制的:默认情况下,通过addEventListener绑定的回调函数中,this关键字就是指向触发当前事件的DOM元素,也就是你点击的tile。如果出现点击后没有给当前元素加类的情况,基本都是以下几种常见问题导致的,对应解决方案如下:
问题1:DOM未加载完成就执行了绑定逻辑
getElementsByClassName返回的是动态HTML集合,如果你的脚本放在head标签里,执行时页面的tile元素还没渲染,拿到的gameBoard是空集合,后续的事件绑定完全没有生效。
解决方案
把全部JS代码放在body标签的末尾,或者包裹在DOM加载完成的事件回调中:
document.addEventListener('DOMContentLoaded', function() { // 你原来的所有代码放在这个回调内部 var gameBoard = document.getElementsByClassName("tile") var playerOne = { "turn": true, "class": "cross" } var playerTwo = { "turn": false, "class": "naught" } for (let i = 0; i < gameBoard.length; i++ ) { gameBoard[i].addEventListener("click", takeTurn) } })
问题2:this指向被其他逻辑修改
如果你的代码中存在其他修改takeTurn指向的逻辑(比如用了箭头函数、bind绑定等),会导致this不指向触发事件的元素。可以直接从事件对象中获取点击目标,写法更稳妥,兼容性也更好。
解决方案
修改takeTurn函数,从事件参数中取触发元素,还可以补充判断避免重复点击同一格子、切换玩家回合的逻辑:
function takeTurn (e) { // e.target 就是实际触发本次点击事件的DOM元素 const currentTile = e.target // 已经有棋子的格子不能重复点击 if(currentTile.classList.contains('cross') || currentTile.classList.contains('naught')) return // 根据当前回合给格子加对应类 if(playerOne.turn) { currentTile.classList.add(playerOne.class) } else { currentTile.classList.add(playerTwo.class) } // 切换玩家回合 playerOne.turn = !playerOne.turn playerTwo.turn = !playerTwo.turn }
内容的提问来源于stack exchange,提问作者Sean Jones
相关产品推荐
相关产品推荐

