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

需求:

  • 左上侧:状态

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

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

  • 父子之间属性传递(props

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

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

    function Square({ value, onSquareClick }) {
    return (

    );
    }

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;
}
相关推荐
铁皮饭盒16 小时前
Bun 哪比 Node.js 快?
javascript·后端
JieE2121 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
candyTong1 天前
RTK 技术原理:一次典型会话里,80% 上下文是怎么省下来的
javascript·后端·架构
_柳青杨1 天前
深入理解 JavaScript 事件循环
前端·javascript
大家的林语冰2 天前
ES5 凉凉,Babel 8 正式发布,默认不再编译为 ES5 和 CJS......
前端·javascript·前端工程化
光影少年2 天前
react批量更新、同步/异步更新场景
前端·react.js·掘金·金石计划
YFF菲菲兔2 天前
completeRoot 源码解析
react.js
weedsfly2 天前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript
用户1733598075372 天前
纯前端 PDF 数字签名实战:Vue 3 + pdf-lib 在浏览器里完成签名嵌入
前端·javascript
JieE2122 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法