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;
}
相关推荐
Juchecar2 分钟前
分析:将现代开源浏览器的JavaScript引擎更换为Python的可行性与操作
前端·javascript·python
非凡ghost1 小时前
AMS PhotoMaster:全方位提升你的照片编辑体验
windows·学习·信息可视化·软件需求
小遁哥2 小时前
也是用上webworker了
react.js·性能优化
伍哥的传说2 小时前
Vue 3.5重磅更新:响应式Props解构,让组件开发更简洁高效
前端·javascript·vue.js·defineprops·vue 3.5·响应式props解构·vue.js新特性
德育处主任2 小时前
p5.js 3D 形状 "预制工厂"——buildGeometry ()
前端·javascript·canvas
Mintopia2 小时前
React 牵手 Ollama:本地 AI 服务对接实战指南
前端·javascript·aigc
Mintopia2 小时前
Next.js 全栈开发基础:在 pages/api/*.ts 中创建接口的艺术
前端·javascript·next.js
小妖6663 小时前
react-router 怎么设置 basepath 设置网站基础路径
前端·react.js·前端框架
xvmingjiang3 小时前
Element Plus 中 el-input 限制为数值输入的方法
前端·javascript·vue.js
云间月13143 小时前
飞算JavaAI智慧教育场景实践:从个性化学习到教学管理的全链路技术革新
学习·飞算javaai挑战赛