乐趣区

手挽手带你学React:一档 React环境搭建,语法规则,基础使用

手挽手带你学 React 入门第一期, 带你熟悉 React 的语法规则, 消除对 JSX 的恐惧感, 由于现在开发中都是使用 ES6 语法开发 React,所以这次也使用 ES6 的模式进行教学,如果大家对 ES6 不熟悉的话, 先去看看 class 相关内容吧,这里我也慢慢带大家一步一步学会 React。
视频教程
视频教程可移步我的个人博客:http://www.henrongyi.top
什么是 React
React 是 Facebook 的一群变态们开发的一个特别牛 X 的框架。它实际上是一个虚拟 DOM,然后在这个 DOM 中,要用什么组件就能飞速加载进来,不要的时候,马上给删咯(实际上就是个前端框架,都是这么个意思,VUE,NG 都是,只不过他们的数据流向不同而已,React 区别就在于,单向数据流。),React 扮演着 MVC 结构中 V 的角色,后面我会用到基于 FLUX 架构的 Redux 让我们的整个项目变成 MVC 架构。总之,React 也是 hie 牛 X 的。
React 的好处都有啥
React 是一款非常牛 X 的前端框架,它的衍生物 React-Native 可以让你开发接近原生体验的 NativeApp, 它适合的范围相当广泛,前端,后端,手机端,都有很好的兼容性。总而言之,hie 牛 X。
React 基础入门
现在的开发中 React 项目实际上都是使用 ES6 语法来编写,并且,我们现在有很多成熟的脚手架可以使用(create-react-app,dva 等),不过国际惯例,我们要从最基础的用法开始编写。我们采用 ES6 写法来进行教学, 同时使用 webpack 工具,这里会用到很多相关配置,大家可以在这个过程中体验 ES6 的精妙。
开始 HelloWord
配置基础 webpack 环境
这里大家可以不去深入理解,先跟着我一步一步配置出来
开始之前,大家可以去官网:https://reactjs.org/ 下载最新的 React(当前版本 v16.7.0) 中文地址:https://react.docschina.org/
由于我们不使用脚手架,所以我们需要先创建我们自己的 webpack 包,第一步
mkdir helloReact
cd helloReact
首先大家命令行输入
webpack v
如果正常出现版本号 并且是 3.6.0 版本,那么我们就可以按照教程继续走下去了如果没有的话 那么我们就需要命令行继续
cnpm i webpack@3.6.0 -S -g

到这里应该可以正常使用 webpack 了
接下来 我们命令行输入
npm init -y // 这实际上是 初始化一个项目 并且全部默认 当然如果你想看看里面有啥的话 就把 - y 拿掉就好了
npm i // 这里是把 webpack 依赖安装到本包内部
npm i webpack-dev-server@2.11.1 –save-dev // 安装本地运行服务器
npm i webpack-cli –save-dev // 依赖脚手架
运行完成以后,我们会得到一个 package.json 文件 打开看看
{
“dependencies”: {
“webpack”: “^3.6.0” // 依赖包和版本
},
“name”: “helloreact”, // 项目名
“version”: “1.0.0”, // 版本号
“main”: “index.js”, // 入口文件
“scripts”: {//npm run 加这里面的 key 就可以快速执行命令行
“test”: “echo \”Error: no test specified\” && exit 1″
},
“author”: “”, // 作者
“license”: “ISC”,
“description”: “” // 简介
}
这里面实际上是我们项目的一些基础信息
我们需要自己配置 webpack 和 babel 这里我们需要创建两个文件这里面我们要设置入口文件,输出文件,babel,webpackServer 等等,这里不做太详细的介绍 大家可以直接复制代码,后面可能会开专门的 webpack 视频课程。小小的介绍一下这些都是干什么用的
babel-core 调用 Babel 的 API 进行转码
babel-loader
babel-preset-es2015 用于解析 ES6
babel-preset-react 用于解析 JSX
babel-preset-stage-0 用于解析 ES7 提案
命令行输入
npm install –save-dev babel-core babel-loader@7.1.5 babel-preset-es2015 babel-preset-react babel-preset-stage-0
接下来我们在 helloReact 文件夹中创建 webpack.config.js 文件
// webpack.config.js 直接复制即可
const path = require(“path”);
module.exports = {
/* 入口 */
entry: path.join(__dirname, ‘src/index.js’),

/* 输出到 dist 文件夹,输出文件名字为 bundle.js*/
output: {
path: path.join(__dirname, ‘./dist’),
filename: ‘bundle.js’
},
/*src 文件夹下面的以.js 结尾的文件,要使用 babel 解析 */
/*cacheDirectory 是用来缓存编译结果,下次编译加速 */
module: {
rules: [{
test: /\.js$/,
use: [‘babel-loader?cacheDirectory=true’],
include: path.join(__dirname, ‘src’)
}]
},
plugins : [],
devServer : {
disableHostCheck: true,
inline: true,
port:9527,
contentBase: path.join(__dirname, “/”),
}
}

接下来我们在 helloReact 文件夹中创建 .babelrc 文件
{
“presets”: [
“es2015”,
“react”,
“stage-0”
],
“plugins”: []
}
然后我们在 package.json 文件的 script 中添加
//package.json
{
“dependencies”: {
“webpack”: “^3.6.0”
},
“name”: “helloreact”,
“version”: “1.0.0”,
“main”: “index.js”,
“scripts”: {
“server”: “webpack-dev-server”,
“build”: “webpack”,
“test”: “echo \”Error: no test specified\” && exit 1″
},
“author”: “”,
“license”: “ISC”,
“description”: “”,
“devDependencies”: {
“babel-core”: “^6.26.3”,
“babel-loader”: “^7.1.5”,
“babel-preset-es2015”: “^6.24.1”,
“babel-preset-react”: “^6.24.1”,
“babel-preset-stage-0”: “^6.24.1”,
“webpack-cli”: “^3.1.2”,
“webpack-dev-server”: “^2.11.1″
}
}

这些配置完了,我们就在 helloReact mkdir src 并且在 src 中创建 index.js 文件在 根路径 helloReact 下创建 index.html 因为这里我们要用到 react 了 所以需要命令行安装一下 react
cnpm install –save react react-dom
html 文件如下
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<meta http-equiv=”X-UA-Compatible” content=”ie=edge”>
<title>Document</title>
</head>
<body>
<div id=”app”></div>
</body>
<script src=”bundle.js”></script>
</html>

js 文件如下

import React from ‘react’; //es6 引入 react
import ReactDom from ‘react-dom’; //es6 引入 reactReacrDom

ReactDom.render(//ReactDom 渲染 <div>hello React</div> 这个 html 标签 到 id=’app’ 这个标签下
<div>Hello React!</div>, document.getElementById(‘app’));

一切都写完了 我们运行服务 npm run server 来看一眼
如果你看到屏幕显示出 Hello React! 那么恭喜你 环境配置完了 咱们可以开始学习 React 了
如果你配置了半天还没配置成功
到我的 github 下载代码吧。。。https://github.com/piexlmax/h…
React 的 Hello World
我们看到上面的代码

import React from ‘react’; //es6 引入 react
import ReactDom from ‘react-dom’; //es6 引入 reactReacrDom

ReactDom.render(//ReactDom 渲染 <div>hello React</div> 这个 html 标签 到 id=’app’ 这个标签下
<div>Hello React!</div>, document.getElementById(‘app’));

这是一个简单的渲染 是不是根本看不到 React 的组件化模式呢?
所以这里 我们需要写一个根部组件,以后的组件都放跟组件里面,这个 JS 就理所当然成了一个入口文件了
这里 我们在 src 下面创建一个 app.js 文件
app.js
import React, {Component} from ‘react’;
// 这里我们引入 react 和 react 的 Component
// 创建 Hello 这个 class(class 属于 ES6 内容)然后继承 Component 我们就成功地创建了一个 react 组件

export default class App extends Component {
render() {
return (
<div>
Hello,World!
</div>
)
}
}
index.js 我们需要改写为这样
import React from ‘react’;
import ReactDom from ‘react-dom’;

import App from ‘./app.js’ // 引入我们的根组件 App
ReactDom.render(// 把 App 渲染到 id=app 的 dom 中
<App/>, document.getElementById(‘app’));
到这里 我们已经实现了一个真正意义上的 Hello World 了!
传说中的 jsx
开始玩 React 了,那就必须要用到 jsx 语法,什么是 jsx 呢?
JSX 是一种 JavaScript 的语法扩展。JSX 与模板语言相似,但它具有 JavaScript 的全部功能。JSX 会被编译为 React.createElement()方法调用,将返回名为“React elements”的普通 JavaScript 对象。
上面代码里我们看到 我们的 html 实际上是在 js 中的 render 函数中书写的,是一个 React 扩展,允许我们编写看起来像 HTML 的 JavaScript。
切记 自定义组件一定要大写字母开头 return 加括号 并且左括号要和 return 在同一行 只能 return 一个标签,其余内容都要在这个标签内部
export default class App extends Component {
render() {
return (
<div>
Hello,World!
</div>
)
}
}
像是这样一段代码,实际上我们真正使用的时候,已经经过了一次编译,编译过后它长这样。
export default class App extends React.Component {
render() {
return (
React.createElement(
‘div’,
‘Hello,World!’
)
);
}
}
下面的这一段代码是不是就不容易理解了?这实际上是 js 可以帮我们去书写 dom 的代码。在 React 中 JSX 你可以理解为我们可以在 js 中写 HTML 代码了 更通俗一点

export default class App extends Component {
// 方法 生命周期 state 等
render() {
return (
// HTML 模板
)
}
}

React 的基本使用方法
state
我们之前学过 VUE,VUE 中每个组件的数据存在自己的 data 中,那么在 React 中,数据存在哪里呢?没错状态 state 中。由于我们这里用的是 ES6 的 class 所以 我们子类 constructor 中必须先调用 super 才能引用 this。所以我们这里应该这么写 state
export default class App extends Component {
constructor(){
super()
this.state={
hello:”hello World”
}
}
render() {
return (
<div>
{this.state.hello}
</div>
)
}
}
这里我们可以看出,我们想要在 render 中使用 js 就需要用一个{} 这里面的内容同样可以书写简单的 js 表达式。
rander 函数中使用 state 和 JS 表达式
export default class App extends Component {
constructor(){
super()
this.state={
hello:”hello World”
}
}
render() {
return (
<div>
<ul>
<li> 展示 state 中的数据:{this.state.hello}</li>
<li> 三元,短路等,这里用三元示例{this.state.hello?” 存在 hello”:” 不存在 hello”}</li>
<li> 简单计算{1+1}</li>
<li>JS 表达式{Math.floor(Math.random()*10)}</li>
</ul>
</div>
)
}
}
方法的声明以及修改 state
声名方法我们有两种模式,一种是直接书写 方法名 (参数){代码段} 模式,这样的模式在调用的时候需要手动 bind(this)还有一种就是使用 es6 的箭头函数,让其 this 指向自身
修改 state 数据需要调用 this.setState()方法 内部接收一个对象 要修改哪个 key 就在对象内部填写这个 key,并且后面的值就是你要修改的内容,如果,key 在 state 中不存在,则会在 state 中增加这个 key
export default class App extends Component {
constructor(){
super()
this.state={
hello:”hello World”
}
}
bye(){
this.setState({
hello:”bye world”
})
}
byebye=()=>{
this.setState({
helloo:”bye world”
})
}
render() {
return (
<div>
<ul>
<li> 非箭头函数:{this.state.hello}</li>
<li> 箭头函数:{this.state.helloo}</li>
</ul>
<button onClick={this.bye.bind(this)}> 无箭头 </button>
{/* 这里使用 bind 来绑定 this 如果传参的话 this.bye.bind(this, 参数 1,参数 2) */}
<button onClick={()=>{this.byebye()}}> 箭头函数 </button>
{/* 这里是箭头函数的默认属性来搞定了 this 问题 如果传参的话()=>{this.byebye(参数 1,参数 2)*/}}
</div>
)
}
}
这里需要注意,只有触发了 state 的变化,才会导致组件的重新渲染
循环语句,条件语句的使用
大家在 vue 中使用 v -for 就能够完成循环生成组件这样的操作了,在 react 中我们应该怎么做呢?
循环语句我们说过 jsx 里面是可以自由自在地使用 js 的 一般情况下我们使用 map 循环
在循环的时候,每一个 return 出来的标签都需要添加 key={键值}“键值”是创建元素数组时需要包含的特殊字符串属性。键值可以帮助 React 识别哪些元素被更改,添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识
export default class App extends Component {
constructor(){
super()
this.state={
arr:[{text:”qm”},{text:” 奇淼 ”},{text:” 大帅逼 ”}]
}
}

render() {
return (
<div>
{/* 我们说过 jsx 里面是可以自由自在地使用 js 的 这里我们来玩一个循环生成 li */}
<ul>
{this.state.arr.map((item,key)=>{
return(<li key={key}>{item.text}</li>)
})}
</ul>
</div>
)
}
}

判断语句判断语句我们一般使用短路表达式 三元表达式来展示我们想要展示的内容,但是如果需要复杂的条件判断,那么我们最好是写一个自执行函数,然后再函数体内你就可以为所欲为了,记住一定要 return 你想要得到的 dom 标签。
export default class App extends Component {
constructor(){
super()
this.state={
arr:[{text:”qm”},{text:” 奇淼 ”},{text:” 大帅逼 ”}]
}
}

render() {
return (
<div>
{/* 简单的三元和短路实例 */}
{this.state.arr.length==3?<div> 我是三元判断的三个 </div>:<div> 我是三元判断的不是三个 </div>}
{this.state.arr.length==3&&<div> 我是短路判断的三个 </div>}
{/* 我们说过 jsx 内部支持简单的表达式 如果我们使用 if 条件句的话 会导致报错 */}
{/*
if(this.state.arr.length==3){
return(<div> 有三个 </div>)
}
*/}
{/* 我们说过 jsx 这已经是 js 代码段而不是简单语句了,我们简单判断可以使用三元或者短路表达式来进行,但是复杂一点的,我们可以使用如下方法 */}
{(()=>{
if(this.state.arr.length==3){
return(<div> 数组有三个元素 </div>)
}else{
return(<div> 数组有不是三个元素 </div>)
}
})()}
</div>
)
}
}

循环判断嵌套有些时候我们需要根据特定条件去循环,然后渲染出筛选过后的数据,这时候就需要循环和判断嵌套使用了,其实也相当简单,我们的循环实际上是一个简单的 js 表达式,内部的 function 中可以随意书写 js,记得 return 就好了
export default class App extends Component {
constructor(){
super()
this.state={
arr:[{text:”qm”},{text:” 奇淼 ”},{text:” 大帅逼 ”}]
}
}

render() {
return (
<div>
{this.state.arr.map((item,key)=>{
if(key%2==0){
return(<div key={key}> 我是可以余 2 的{item.text}</div>)
}else{
return(<div key={key}> 我是不能余 2 的{item.text}</div>)
}
})}
</div>
)
}
}

获取 DOM(Refs)
有些时候我们不得不去操作 DOM,那这时候 我们需要用到 ref 属性
React 支持一个可以附加到任何组件的特殊属性 ref。ref 属性可以是一个字符串或一个回调函数。当 ref 属性是一个回调函数时,函数接收底层 DOM 元素或类实例(取决于元素的类型)作为参数。这使你可以直接访问 DOM 元素或组件实例。
另外这里应该注意 不要过度使用 Refs。
export default class App extends Component {
constructor(){
super()
this.state={
arr:[{text:”qm”},{text:” 奇淼 ”},{text:” 大帅逼 ”}]
}
}

render() {
return (
<div>
{this.state.arr.map((item,key)=>{
if(key%2==0){
return(<div ref=”link” key={key}> 我是可以余 2 的{item.text}</div>)
{/* 这样我们可以通过 this.refs.link 获取到这个 dom 并且操作 dom 了 */}
}else{
return(<div key={key}> 我是不能余 2 的{item.text}</div>)
}
})}
</div>
)
}
}

总结
到这里我们已经学会了 React 的基本组件内部的操作了,React 相对于 Vue 来说更加灵活,但是唯一的缺点是数据流是单向的,必须通过 setState 来修改,对于处理表单来说会有些麻烦,不过有些 UI 框架,插件帮我们处理了这些大麻烦。写写玩玩吧 React 还是比较简单的。

退出移动版