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;
}
相关推荐
jump_jump2 小时前
基于 Squoosh WASM 的浏览器端图片转换库
前端·javascript·性能优化
落羽凉笙5 小时前
Python学习笔记(3)|数据类型、变量与运算符:夯实基础,从入门到避坑(附图解+代码)
笔记·python·学习
Quintus五等升5 小时前
深度学习①|线性回归的实现
人工智能·python·深度学习·学习·机器学习·回归·线性回归
阿珊和她的猫7 小时前
IIFE:JavaScript 中的立即调用函数表达式
开发语言·javascript·状态模式
jz_ddk7 小时前
[学习] 卫星导航的码相位与载波相位计算
学习·算法·gps·gnss·北斗
智商偏低7 小时前
JSEncrypt
javascript
华清远见成都中心7 小时前
人工智能要学习的课程有哪些?
人工智能·学习
hssfscv8 小时前
Javaweb学习笔记——后端实战2_部门管理
java·笔记·学习
OEC小胖胖8 小时前
01|从 Monorepo 到发布产物:React 仓库全景与构建链路
前端·react.js·前端框架
白帽子黑客罗哥8 小时前
不同就业方向(如AI、网络安全、前端开发)的具体学习路径和技能要求是什么?
人工智能·学习·web安全