React实战学习(一)_棋盘设计

需求:

  • 左上侧:状态

  • 左下侧:棋盘,保证胜利就结束 和 下过来的不能在下

  • 右侧:"时光机",保证可以回顾,索引
    语法:

  • 父子之间属性传递(props

  • 子父组件传递(写法上!回调函数,若与前者相同会出现无限渲染)

    //父组件中声明
    <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
    //子组件接收或发射

    function Square({ value, onSquareClick }) {
    return (
    <button className="square" onClick={onSquareClick}>
    {value}
    </button>
    );
    }

Idea 时光机:

  • 不改动原数组,slice()拷贝原数组,[...history,squares]存各个时间数据
  • 若与每一步索引有关,[...history.slice(0, currentMove + 1), nextSquares]
复制代码
import { useState } from 'react';

function Square({ value, onSquareClick }) {
    return (
        <button className="square" onClick={onSquareClick}>
            {value}
        </button>
    );
}

function Board({ xIsNext, squares, onPlay }) {
    function handleClick(i) {
        if (calculateWinner(squares) || squares[i]) {
            return;
        }
        const nextSquares = squares.slice();
        if (xIsNext) {
            nextSquares[i] = 'X';
        } else {
            nextSquares[i] = 'O';
        }
        onPlay(nextSquares);
    }

    const winner = calculateWinner(squares);
    let status;
    if (winner) {
        status = 'Winner: ' + winner;
    } else {
        status = 'Next player: ' + (xIsNext ? 'X' : 'O');
    }

    return (
        <>
            <div className="status">{status}</div>
            <div className="board-row">
                <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
                <Square value={squares[1]} onSquareClick={() => handleClick(1)} />
                <Square value={squares[2]} onSquareClick={() => handleClick(2)} />
            </div>
            <div className="board-row">
                <Square value={squares[3]} onSquareClick={() => handleClick(3)} />
                <Square value={squares[4]} onSquareClick={() => handleClick(4)} />
                <Square value={squares[5]} onSquareClick={() => handleClick(5)} />
            </div>
            <div className="board-row">
                <Square value={squares[6]} onSquareClick={() => handleClick(6)} />
                <Square value={squares[7]} onSquareClick={() => handleClick(7)} />
                <Square value={squares[8]} onSquareClick={() => handleClick(8)} />
            </div>
        </>
    );
}

export default function Game() {
    //const [xIsNext, setXIsNext] = useState(true);
    //初始化为一个[[null,null.......null]],二维数组
    const [history, setHistory] = useState([Array(9).fill(null)]);
    const [currentMove, setCurrentMove ]= useState(0);

    // const currentSquares = history[history.length-1];
    const currentSquares = history[currentMove];

    const xIsNext= currentMove % 2 === 0;
    function handlePlay(nextSquares) {
        //如果 history 为 [[null,null,null], ["X",null,null]],nextSquares 为 ["X",null,"O"],则新的 [...history, nextSquares] 数组将为 [[null,null,null], ["X",null,null], ["X",null,"O"]]
        // setHistory([...history, nextSquares]);
        // setXIsNext(!xIsNext);
        const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
        setHistory(nextHistory);
        setCurrentMove(nextHistory.length - 1)
    }

    const moves=history.map((squares,move)=>{
        let description;
        if (move>0){
            description='Go to move#' +move;
        }else {
            description='Go to game start';
        }
        return(
            <li key={move}>
                <button onClick={()=>jumpTo(move)}>{description}</button>
            </li>
        )
    })
    function jumpTo(nextMove){
        setCurrentMove(nextMove);
    }
    return (
        <div className="game">
            <div className="game-board">
                <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
            </div>
            <div className="game-info">
                <ol>{moves}</ol>
            </div>
        </div>
    );
}

function calculateWinner(squares) {
    const lines = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6],
    ];
    for (let i = 0; i < lines.length; i++) {
        const [a, b, c] = lines[i];
        if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
            return squares[a];
        }
    }
    return null;
}
相关推荐
能不能别报错4 分钟前
K8s学习笔记(十九) K8s资源限制
笔记·学习·kubernetes
我胡为喜呀13 分钟前
Vue3 中的 watch 和 watchEffect:如何优雅地监听数据变化
前端·javascript·vue.js
十安_数学好题速析42 分钟前
倍数关系:最多能选出多少个数
笔记·学习·高考
vue学习1 小时前
docker 学习dockerfile 构建 Nginx 镜像-部署 nginx 静态网
java·学习·docker
JamSlade2 小时前
流式响应 sse 系统全流程 react + fastapi为例子
前端·react.js·fastapi
徐同保2 小时前
react useState ts定义类型
前端·react.js·前端框架
liangshanbo12152 小时前
React 19 vs React 18全面对比
前端·javascript·react.js
Never_Satisfied3 小时前
在 JavaScript 中,删除数组中内容为xxx的元素
java·前端·javascript
_菜鸟果果3 小时前
Vue3+echarts 3d饼图
前端·javascript·echarts