You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React路径寻踪应用问题:仅改点击单元格类及实现拖拽绘墙

解决路径寻踪应用的墙体绘制问题

嘿,我来帮你搞定这个问题!你现在遇到的核心问题是用了一个全局的wall状态来控制所有单元格的样式,所以一点击所有单元格都变成墙了。咱们分两步来解决:先修复单个点击单元格变墙的问题,再实现拖拽连续绘制墙体的功能。

第一步:修复单个单元格点击切换墙体状态

首先,我们需要把状态从全局的wall布尔值,改成存储每个单元格是否为墙的结构。这里用一个对象walls来记录,键是行号-列号的字符串,值是布尔值表示是否是墙。

修改你的Grid.js代码如下:

import React, { Component } from "react";

export class Grid extends Component {
  constructor(props) {
    super(props);
    this.state = {
      walls: {}, // 存储每个单元格的墙体状态,格式:`${row}-${col}: boolean`
      isDragging: false, // 标记是否处于拖拽绘制状态
    };
    // 绑定事件方法,避免this指向问题
    this.toggleWall = this.toggleWall.bind(this);
    this.handleMouseDown = this.handleMouseDown.bind(this);
    this.handleMouseEnter = this.handleMouseEnter.bind(this);
    this.handleMouseUp = this.handleMouseUp.bind(this);
  }

  componentDidMount() {
    // 监听全局mouseup事件,防止拖拽移出网格后无法停止绘制
    document.addEventListener("mouseup", this.handleMouseUp);
  }

  componentWillUnmount() {
    // 组件卸载时移除全局事件监听
    document.removeEventListener("mouseup", this.handleMouseUp);
  }

  // 切换指定单元格的墙体状态
  toggleWall(row, col) {
    const cellKey = `${row}-${col}`;
    this.setState(prevState => ({
      walls: {
        ...prevState.walls,
        [cellKey]: !prevState.walls[cellKey]
      }
    }));
  }

  // 鼠标按下时,开启拖拽状态并切换当前单元格
  handleMouseDown(row, col) {
    this.setState({ isDragging: true });
    this.toggleWall(row, col);
  }

  // 鼠标进入单元格时,如果处于拖拽状态,切换墙体
  handleMouseEnter(row, col) {
    if (this.state.isDragging) {
      this.toggleWall(row, col);
    }
  }

  // 鼠标松开时,关闭拖拽状态
  handleMouseUp() {
    this.setState({ isDragging: false });
  }

  render() {
    let rows = [];
    // 注意:把列的生成放到行循环里,确保每个行的列对应正确的行号
    for (let row = 0; row < 25; row++) {
      let columns = [];
      for (let col = 0; col < 60; col++) {
        const cellKey = `${row}-${col}`;
        const isWall = this.state.walls[cellKey];
        columns.push(
          <td
            className={isWall ? "wall" : "grid"}
            onClick={() => this.toggleWall(row, col)}
            onMouseDown={() => this.handleMouseDown(row, col)}
            onMouseEnter={() => this.handleMouseEnter(row, col)}
            id={cellKey}
            key={cellKey}
          ></td>
        );
      }
      rows.push(
        <tr id={row.toString()} key={row.toString()}>
          {columns}
        </tr>
      );
    }
    return (
      <div>
        <table className="grid">
          <tbody>{rows}</tbody>
        </table>
      </div>
    );
  }
}

export default Grid;

关键修改点说明:

  • 状态结构调整:用walls对象替代全局wall,每个单元格的状态独立存储,避免一键全改的问题
  • 事件绑定:给每个单元格添加onMouseDown、onMouseEnter事件,配合全局mouseup实现拖拽绘制的完整逻辑
  • 循环逻辑优化:把列的生成放到行循环内部,确保每个单元格能正确对应自己的row和col索引
  • 状态更新:使用函数式setState来确保状态更新的正确性,避免异步更新导致的逻辑错误

第二步:验证功能

现在你可以测试两个核心功能:

  • 单个点击任意单元格,只会切换该单元格的墙体状态,不会影响其他单元格
  • 按住鼠标左键拖拽,经过的单元格会连续变成墙体(再次拖拽同一区域可以取消墙体)

你的App.js和CSS代码不需要修改,保持原样即可。

内容的提问来源于stack exchange,提问作者RandyBeans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:43:11