jQuery开发象棋游戏时如何存储两次点击的元素属性
问题排查
你的代码出问题根本不是var和let的特性差异,是三个硬伤:
- 跨点击需要留存的选中状态,你只零散存了棋子id和格子value,棋子本身的class、value属性根本没存,更新DOM的时候拿不到对应值。
- 每次点击事件触发时,你在回调内部声明的
value/id/color都是当前点击元素的属性,第一次点棋子存的值,第二次点格子的时候会被直接覆盖,根本留不住。之前用let/const代码直接跑不起来,是因为你把需要跨点击存值的变量声明在了回调内部,回调执行完变量就销毁了,下次点击访问直接报引用错误。 - 走完一步棋之后你没有重置选中状态,
selectedPiece和moveToSquare一直有值,后续点击永远进不了选中判断的分支。另外你写的更新DOM的HTML字符串有语法错误,<td> class=${color}把属性写到了td标签外面,浏览器根本识别不到,DOM结构更新完就乱了。
修复方案
直接把状态变量挪到事件回调外面存全量属性,不要每次重写innerHTML,用jQuery方法直接修改元素属性,走完棋重置状态就行,可直接替换的参考代码如下:
// 注意:这两个变量必须声明在click事件回调的外部,不要写到回调里面 let selectedPiece = null; let moveToSquare = null; $(document).on("click", function (event) { // 直接拿事件目标元素就行,不用elementFromPoint多此一举 const $currentEl = $(event.target); const elId = $currentEl.attr('id'); const elValue = $currentEl.attr('value'); const elClass = $currentEl.attr('class'); // 点到棋盘外的区域直接跳过 if (!elId) return; // 第一次点击:选中待移动棋子 if (selectedPiece === null && elId.includes('piece')) { selectedPiece = { $el: $currentEl, id: elId, value: elValue, pieceClass: elClass }; enlargeBackground(); return; } // 第二次点击:选中落子空格,触发行棋 if (selectedPiece !== null && moveToSquare === null && elId.includes('cell')) { moveToSquare = { $el: $currentEl, id: elId }; move(); return; } }); // 棋盘DOM更新逻辑 function refreshBoard() { // 原棋子位置重置为空白格 selectedPiece.$el .attr('id', 'cell') .removeAttr('value') .attr('class', 'cell') .empty(); // 目标空格替换为移动后的棋子 moveToSquare.$el .attr('id', selectedPiece.id) .attr('value', selectedPiece.value) .attr('class', selectedPiece.pieceClass); // 走完一步必须重置选中状态,否则后续走棋判断全部失效 selectedPiece = null; moveToSquare = null; } // 你原有的move函数保留合法性判断,判断可走之后直接调用refreshBoard()即可 function move() { // 原有走棋规则校验逻辑... // 校验通过后更新棋盘 refreshBoard(); }
避坑提醒
- 不要在事件回调内部声明需要跨多次事件留存的变量,这类状态必须放在回调外部的作用域,否则每次触发事件都会重新初始化/覆盖变量值。
- 更新已有DOM元素的属性优先用
.attr()这类原生/jQuery提供的属性修改方法,不要直接拼字符串覆写innerHTML,很容易破坏DOM结构、丢失已绑定的事件。 - 所有多步操作的状态,在操作流程走完之后必须手动重置为初始值,不然状态判断逻辑会全部混乱。
内容的提问来源于stack exchange,提问作者mrt
相关产品推荐
相关产品推荐

