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 小时前
若依Vue 项目多子路径配置
前端·javascript·vue.js
2601_949593654 小时前
基础入门 React Native 鸿蒙跨平台开发:模拟智能音响
react native·react.js·harmonyos
微露清风4 小时前
系统性学习Linux-第二讲-基础开发工具
linux·运维·学习
xiaoqi9224 小时前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin1233225 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
阳光九叶草LXGZXJ5 小时前
达梦数据库-学习-48-DmDrs控制台命令(同步之Manager、CPT模块)
linux·运维·数据库·sql·学习
biuyyyxxx5 小时前
Python自动化办公学习笔记(一) 工具安装&教程
笔记·python·学习·自动化
烬头88216 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos
pas1366 小时前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js
2601_949833397 小时前
flutter_for_openharmony口腔护理app实战+预约管理实现
android·javascript·flutter