梁朋杰

  • 主页
  • 所有文章
所有文章 友链 关于我

梁朋杰

  • 主页
  • 所有文章

React井字小游戏

2017-07-05

React井字小游戏

在React官方文档中,有一个很适合菜鸟练手的React项目,React井字小游戏。
在这篇教程里,主要涉及到了es6的一些语法。

现在我们这里已经搭建好一个基本的游戏模板,
你可以点击这里进行下载

首先来搭建React的基本运行环境

1、首先需要你安装最新版的node
2、点击创建新的React项目
3、删除掉src文件夹下的所有文件
4、在 src/ 文件夹下新建一个名为 index.css 的文件并拷贝 这里的 CSS 代码 到文件中。
5、在 src/ 文件夹下新建一个名为 index.js 的文件并拷贝 这里的 JS 代码 到文件中, 并在此文件的最开头加上下面几行代码:

1
2
3
4
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

在完成上述操作以后,可以运行cmd进行依赖的安装,运行项目以后,点击http://localhost:3000/就可以看到这样的呈现效果
呈现的效果

不过现在还没有添加功能,接下来给模板添加一些功能

1
2
3
4
5
6
7
8
//棋盘上单独的一个格子
function Square(props){
return(
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}

props && state

props用于各个组件之间传递数据,state用于组件内部更新状态
react推荐凡是组件通信数据都是通过props。他与state的区别在于,state是通过setState来更新的,
props是通过组件的生命周期来更新的,这意味着,组件生命周期不发生变化,props是不会变的.

子组件Square上绑定的onClick事件是从父组件Board由props.onClick属性传递过来的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//棋盘主体
class Board extends React.Component {
//这里渲染出每一个棋格
renderSquare(i) {
return <Square
value={this.props.squares[i]}
onClick={()=>this.props.onClick(i)}
/>;
}
render() {
return (
<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>
);
}
}

Game组件里编写了我们小游戏的基本逻辑,在这里要阐述一下React的状态提升,以及它的必要性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//Game 组件则为我们即将要编写的代码预留了一些位置
class Game extends React.Component {
//保存初始化状态
constructor(){
super();
this.state={
history:[{
squares:Array(9).fill(null),
}],
stepNumber:0,
xIsNext:true,
}
}
handleClick(i){
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current=history[history.length-1];
const squares=current.squares.slice();
//const squares=this.state.squares.slice();//.slice()方法将之前的数组数据深拷贝到一个新的数组中
if(calculateWinner(squares)||squares[i]){
return;
}
squares[i]=this.state.xIsNext?'X':'O';
this.setState({
history:history.concat([{
squares:squares
}]),
stepNumber: history.length,
xIsNext:!this.state.xIsNext,
});
}
jumpTo(step) {
this.setState({
stepNumber: step,
xIsNext: (step % 2) ? false : true,
});
}
render() {
const history =this.state.history.slice(0,this.state.stepNumber+1);
const current =history[this.state.stepNumber];
const winner =calculateWinner(current.squares);
const moves=history.map((step,move)=>{
const desc=move?
'Move #'+move:
'Game start';
return(
<li key={move}>
<a href="#" onClick={()=>this.jumpTo(move)}>{desc}</a>
</li>
)
});
let status;
if(winner){
status="Winner:"+winner;
}else{
status="Next player:"+(this.state.xIsNext?'X':'O')
}
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={(i)=>this.handleClick(i)}/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
}
当你遇到需要同时获取多个子组件数据,或者两个组件之间需要相互通讯的情况时,把子组件的 state 数据提升至其共同的父组件当中保存。之后父组件可以通过props 将状态数据传递到子组件当中。这样应用当中的状态数据就能够更方便地交流共享了。

在使用 JavaScript classes 时,你必须调用 super(); 方法才能在继承父类的子类中正确获取到类型的 this 。

在 React 组件的构造方法 constructor 当中,你可以通过 this.state 为该组件设置自身的状态数据。试着把棋盘格子变化的数据储存在组件的state 当中:

1
2
3
4
5
6
7
8
9
10
11
//es6中的语法,把组件中的初始化状态,保存在constructor中
constructor(){
super();
this.state={
history:[{
squares:Array(9).fill(null),
}],
stepNumber:0,
xIsNext:true,
}
}

在constructor中存储了状态数据

handleClick用户操作的基本方法都由这里进行挂载派发,传递,然后子组件由props进行接收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
handleClick(i){
//这里保存着棋盘的状态历史
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[history.length-1];
const squares = current.squares.slice();
//const squares=this.state.squares.slice();//.slice()方法将之前的数组数据深拷贝到一个新的数组中
if(calculateWinner(squares)||squares[i]){
return;
}
squares[i]=this.state.xIsNext?'X':'O';
this.setState({
history:history.concat([{
squares:squares
}]),
stepNumber: history.length,
xIsNext:!this.state.xIsNext,
});
}
赏

谢谢你请我吃糖果

  • React

扫一扫,分享到微信

微信分享二维码
node第二天
Vue的世界
© 2018 梁朋杰
Hexo Theme Yilia by Litten
  • 所有文章
  • 友链
  • 关于我

tag:

  • JS
  • React
  • React表单
  • Vue px rem
  • Vuex
  • Vue axios vuex vue-router
  • Vue
  • http
  • node nvm
  • node utility
  • Vue Mongdb Koa

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • React教程
  • React菜鸟教程
  • React入门实例(阮一峰)
  • React Router使用教程(阮一峰)
  • React介绍及实例教程
乐于分享,喜欢环境音乐,爱看动漫,偶尔写写技术博客的小程一枚...