前言
主要练习React官网中的题目,使用React达成做出圈圈叉叉的小游戏,练习项目为
利用props传递资料建立互动式Component提升StateStep1 建立React Components
主要建立三个Components : Game,Board,Square
Components Tree :
Game :
import React from "react"import Board from "./Board"class Game extends React.Component{ render() { return( <Board /> ) }}ReactDOM.render(<Game />,document.getElementById("root"));
Board :
import React from "react"import Square from "./Square"class Board extends React.Component{ render() { return( <Square /> ) }}export default Board;
Square :
import React from "react"class Square extends React.Component{ render() { return( <div> Square Component </div> ) }}export default Square;
Step2 利用props传递资料
在Board中利用props将数据传递给Square后将他选染出来
Board :
class Board extends React.Component{ renderSquare(i) { return <Square value={i} />; } render() { const status = 'Next player: X'; return( <div> <div className="status">{status}</div> <div className="board-row"> {this.renderSquare(0)} //将数字里用props传递给Square {this.renderSquare(1)} {this.renderSquare(2)} </div> <div className="board-row"> {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} </div> <div className="board-row"> {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} </div> </div> ) }}
Square :
class Square extends React.Component{ render() { return( <button className="square"> {this.props.value} //接收父层(Board)所传递的数字 </button> ) }}
结果 :
Step3 建立互动Component
当点击 Square component 时,能在方格中填入一个 X。
Square :
1.在Square中建立一个state以初始化Square Vaule中的值
2.建立一个function,当被点击时触发改变state中的值("" -> "X")
class Square extends React.Component{ //Step1 : 建立constructor以初始化state中的Value constructor(props) { super(props); this.state = { value:"" } } //Step2 : 建立一个function当点击时触发 handleClick = (e) => { this.setState({ value : "X" //利用setState改变State中的值 }); } render() { return( <button className="square" onClick={this.handleClick}> //点击时触发 {this.state.value} </button> ) }}
Step3 : 提升State
为了一次性的纪录这九个方格中的值,所以需要将state提升到父层(Board)。
Board :
1.将state提升到父层(Board)
2.在父层建立当Square被点击时触发的function
3.将State的Value与handleClick function藉由props传递给Square
class Board extends React.Component{ //Step1 : 将state提升到Board constructor(props) { super(props); this.state = { squares : Array(9).fill("") //建立大小为9的阵列并填入"" }; } //Step2 :建立当Square被点击时触发的function handleClick = (i) => { const squares = this.state.squares.slice(); squares[i] = 'X'; this.setState({squares: squares}); } renderSquare(i) { //Step3 :利用props传递给子层(Square) return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)}/>; } render() { const status = 'Next player: X'; return( <div> <div className="status">{status}</div> <div className="board-row"> {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)} </div> <div className="board-row"> {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} </div> <div className="board-row"> {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} </div> </div> ) }}
Square :
1.移除自身state
2.将this.state更改为this.props(参数由父层传递)
class Square extends React.Component{ //Step1 : 移除自身state render() { return( //Step2 : 将this.state更改为this.props(参数由父层传递) <button className="square" onClick={() => this.props.onClick()}> {this.props.value} </button> ) }}
结果 :
Step4 : 加入轮流功能
会将第一步的预设值设定为"X",并设定一个boolean来判断由"X"改为"O"以达到轮流的功能。
Board :
1.新增一个boolean xIsNext 来判断符号的轮流
2.在handleClick function中建立判断式以判断现在的符号的状况(xIsNext true or false)
3.反转xIsNext状态
class Board extends React.Component{ constructor(props) { super(props); this.state = { squares : Array(9).fill(""), xIsNext : true //Step1 :新增一个boolean xIsNext }; } handleClick = (i) => { const squares = this.state.squares.slice(); squares[i] = this.state.xIsNext?"X":"O"; //Step2 :判断现在的符号的状况 this.setState({ squares : squares, xIsNext : !this.state.xIsNext //Step3 :反转xIsNext状态 }); } renderSquare(i) { return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)}/>; } render() { const status = 'Next player: X'; return( <div> <div className="status">{status}</div> <div className="board-row"> {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)} </div> <div className="board-row"> {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} </div> <div className="board-row"> {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} </div> </div> ) }}
结果 :
Step 5 : 决定胜负
建立一个function已检测哪一方胜利,并在建立一个funciton再分出胜负后清除表格中的符号。
function calculateWinner :
建立一个九个 square 的 array,记录各个胜利条件检测输入的参数是否有达成获胜条件(若达成条件则输出获胜的符号)export const calculateWinner = (squares) => { //Step 1:建立一个九个胜利条件的Array 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]; //Step 2:检测输入的参数是否有达成获胜条件 if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { return squares[a]; //输出获胜的符号 } } return null;}
Board :
1.建立一个参数(Winner)用来存取function calculateWinner计算的结果
2.利用Winner来判断是否达成获胜条件
3.新增一个按钮用来重新开始
4.新增当重新开始按钮被点击后触发的function
import {calculateWinner} from "./calculateWinner" //include functionclass Board extends React.Component{ constructor(props) { super(props); this.state = { squares : Array(9).fill(""), xIsNext : true }; } handleClick = (i) => { const squares = this.state.squares.slice(); squares[i] = this.state.xIsNext?"X":"O"; this.setState({ squares : squares, xIsNext : !this.state.xIsNext }); } renderSquare(i) { return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)}/>; } //Step 4:当重新开始按钮被点击后触发的function Reset = () => { const emply = this.state.squares.fill(""); this.setState({ squares : emply, xIsNext : true }); } render() { //Step 1:建立一个参数(Winner)用来存取function calculateWinner计算的结果 const Winner = calculateWinner(this.state.squares); let status; //Step 2:判断是否达成获胜条件 if(Winner) { status = "Winner :" + Winner; alert(status); } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } return( <div> <div className="status">{status}</div> <div className="board-row"> {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)} </div> <div className="board-row"> {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} </div> <div className="board-row"> {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} </div> <dic> //Step 3:新增一个按钮用来重新开始 <button onClick={this.Reset}>ReStart</button> </dic> </div> ) }}
结果:
参考资料 :
React学习指南