一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情。
前言
最近趁上班空闲的时候比较空闲,由于只会用Vue的原因,所以也想学学新的知识,于是想自学一下React,打开React的官网发现React的新手教程相对于Vue来说是比较友好的,可以有俩种学习的方式,可以从基础开始学习,也可以从一个demo开始学习,于是选择了从demo开始出发,最后也做了一个改版。
React工具
React 有个比较好的调试方案,那就是官方文档指出的 react devtools ,可以针对性的做一些代码的调试。所以我可以安装了个插件玩玩
chorme的网上商店需要科学上网才能得到,如果检测到当前web是 react 项目,右上角的工具小图标(地址栏右侧)会发生改变,这样我们打开控制台就可以看到整个react的树结构,有利于我们开发的时候更好的处理问题。
小demo
这个是利用了官方提供的demo的模板,我将九宫格的小游戏改成了一个九宫格转盘游戏,点击开始游戏的时候红色方块会在九宫格中随机跳动,后续将给他改成一个打地鼠的游戏。
React的结构
React整个项目的入口和vue没什么区别,都通过一个index.html当做如果,然后按照官方文档的教程,在src文件夹下新建index.js和index.css,而没有html文件,一些dom都是通过JSreturn的方式返回的。react的组件化我感觉比vue的更加明显一点,主要是通过render先返回一个作为父组件的dom,父组件的dom中也可以放一个子组件,整个Game的类作为一个父组件,通过ReactDOM.render的方式显示到页面上,在Game的类中我们可以写一些函数,比如我写的restart函数,通过constructor可以继承一些父组件传过来的数据,也可以设置一些state数据作为共享数据使用
class Game extends React.Component {
constructor(props){
super(props);
this.state = {
history: [{
square: Array(9).fill(null),
}],
// stepNumber: 0,
xIsNext : true,
activeIndex:1
}
}
restrat() {
setInterval(() => {
this.setState({
activeIndex:Math.round(Math.random()*8+0)
})
console.log(this.state.activeIndex)
}, 250);
}
render() {
const history = this.state.history;
return (
<div className="game">
<div className="game-board">
<Board
activeInd={this.state.activeIndex}
/>
</div>
<div className="game-info">
</div>
<div>
<button onClick={()=>this.restrat()} >开始游戏</button>
</div>
</div>
);
}
}
ReactDOM.render(
<Game />
,
document.getElementById('root')
);
又比如我在Board中设置了renderSquare函数,在render的中返回的dom中又可以用到自己的函数,并且可以通过父组件返回的数据做判断,这里我是判断当前随机的index是否和九宫格的index是否相同,然后去改变背景颜色
class Board extends React.Component {
constructor(props){
super(props);
this.state = {
square : Array(9).fill(null),
xIsNext : true,
}
}
renderSquare(i) {
if(this.props.activeInd==i){
return <Square
activeClass = 'active'
value1={this.props.activeInd}
/>;
}else{
return <Square
/>;
}
}
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>
);
}
}
最后是一个子组件是小格子的,react的组件不仅可以通过类返回,也可以通过function的方式,然后是返回动态节点的格式,{props.value} {props.value1?
: ''},中间的style格式也是通过先声明一个样式sty对象,然后再通过模板语法进行显示function Square(props) {
let imgUrl = './mouse.jpg'
let sty = {
background:'red',
height: '100%',
width: '100%'
}
return (
<div className="square" >
{props.value}
{props.value1
? <div style={sty}></div>
: ''
}
</div>
);
}
到这里三个组件已经做完了,Game也被显示到页面上,至此整个页面也已经完成我们可以看看效果
把主要文件给大家分享一下
//index.css
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol, ul {
padding-left: 30px;
}
.board-row:after {
clear: both;
content: "";
display: table;
}
.status {
margin-bottom: 10px;
}
.square {
background: #fff;
border: 1px solid #999;
float: left;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 34px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 34px;
}
.square:focus {
outline: none;
}
.kbd-navigation .square:focus {
background: #ddd;
}
.game {
display: flex;
flex-direction: row;
}
.game-info {
margin-left: 20px;
}
.activeClass{
background-color: red;
}
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
function Square(props) {
let imgUrl = './mouse.jpg'
let sty = {
background:'red',
height: '100%',
width: '100%'
}
// const changeSty = {props.value1?sty:''}
return (
<div className="square" >
{props.value}
{props.value1
? <div style={sty}></div>
: ''
}
</div>
);
}
class Board extends React.Component {
constructor(props){
super(props);
this.state = {
square : Array(9).fill(null),
xIsNext : true,
}
}
renderSquare(i) {
if(this.props.activeInd==i){
return <Square
activeClass = 'active'
value1={this.props.activeInd}
/>;
}else{
return <Square
/>;
}
}
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>
);
}
}
class Game extends React.Component {
constructor(props){
super(props);
this.state = {
history: [{
square: Array(9).fill(null),
}],
// stepNumber: 0,
xIsNext : true,
activeIndex:1
}
}
restrat() {
console.log(222);
setInterval(() => {
this.setState({
activeIndex:Math.round(Math.random()*8+0)
})
console.log(this.state.activeIndex)
}, 250);
}
render() {
const history = this.state.history;
return (
<div className="game">
<div className="game-board">
<Board
activeInd={this.state.activeIndex}
/>
</div>
<div className="game-info">
</div>
<div>
<button onClick={()=>this.restrat()} >开始游戏</button>
</div>
</div>
);
}
}
// ========================================
ReactDOM.render(
<Game />
,
document.getElementById('root')
);
function calculateWinner(square) {
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 (square[a] && square[a] === square[b] && square[a] === square[c]) {
return square[a];
}
}
return null;
}