React/JS象棋游戏中element.remove()与element.append()冲突问题求助
象棋游戏拖拽吃子问题修复
你这段代码的核心问题很明确:执行ev.target.remove()之后,ev.target已经从DOM中被移除了,再调用ev.target.append()根本不会把白棋子加到任何地方,自然屏幕上啥都看不到。
临时DOM操作修复方案
如果先不改React的思路,只修复当前代码,你可以先拿到黑棋子的父容器(也就是棋盘格子),移除黑棋子后,把白棋子加到父元素里:
function drop(ev) { ev.preventDefault(); ev.target.style.backgroundColor = ev.target.dataset.squarecolor; let movingPiece = JSON.parse(ev.dataTransfer.getData("Text")); if (movingPiece.color === 'white' && ev.target?.dataset?.color === 'black' && ev.target.nodeName === 'IMG') { // 先拿到黑棋子的父容器(棋盘格子) const square = ev.target.parentElement; // 移除黑棋子 ev.target.remove(); // 把白棋子加到格子里 square.append(document.getElementById(movingPiece.id)); } }
React规范做法(推荐)
但更符合React开发逻辑的是用状态管理棋子位置,而不是直接操作DOM——React是数据驱动视图的,手动操作DOM很容易引发渲染异常:
- 用
useState维护一个对象,记录每个棋盘格子对应的棋子信息(颜色、类型、ID等)。 - 拖拽开始时,记录要移动的棋子的起始位置和信息。
- 拖拽结束时,更新状态:把目标格子的棋子替换成当前移动的棋子,同时清空起始格子的棋子。
- 组件根据状态自动渲染每个格子的棋子,完全不用手动操作DOM。
简化示例:
import { useState } from 'react'; const ChessBoard = () => { // 初始化棋盘状态,key是格子坐标,value是棋子信息 const [boardState, setBoardState] = useState({ 'a1': { id: 'white-rook-1', color: 'white', type: 'rook' }, 'a8': { id: 'black-rook-1', color: 'black', type: 'rook' }, // ... 其他棋子 }); const handleDragStart = (e, piece, position) => { e.dataTransfer.setData("Text", JSON.stringify({ piece, position })); }; const handleDrop = (e, targetPosition) => { e.preventDefault(); const { piece, startPosition } = JSON.parse(e.dataTransfer.getData("Text")); // 判断是否可以吃子(白吃黑) const targetPiece = boardState[targetPosition]; if (piece.color === 'white' && targetPiece?.color === 'black') { setBoardState(prev => ({ ...prev, // 清空起始位置 [startPosition]: null, // 目标位置替换成当前棋子 [targetPosition]: piece })); } }; // 渲染棋盘格子和棋子 return ( <div className="board"> {Object.keys(boardState).map(position => ( <div key={position} className="square" onDrop={(e) => handleDrop(e, position)} onDragOver={(e) => e.preventDefault()} > {boardState[position] && ( <img id={boardState[position].id} src={`/images/${boardState[position].color}-${boardState[position].type}.png`} draggable onDragStart={(e) => handleDragStart(e, boardState[position], position)} data-color={boardState[position].color} /> )} </div> ))} </div> ); };
内容的提问来源于stack exchange,提问作者Simao
相关产品推荐
相关产品推荐

