视频教程

本文章在B站配有视频教程

课程目标

  • 了解最常用的React概念和相关术语,例如JSX,组件,属性(Props),状态(state)。
  • 构建一个非常简单的React应用程序,以阐述上述概念。

最终效果

创建React应用

helloworld

(1)安装node.js     官网链接

(2)打开cmd 窗口 输入

npm install --g create-react-app
npm install --g yarn

(-g 代表全局安装)

如果安装失败或较慢。需要换源,可以使用淘宝NPM镜像,设置方法为:npm config set registry https://registry.npm.taobao.org,设置完成后,

重新执行

cnpm install --g create-react-app
cnpm install --g yarn

安装 creat-react-app 功能组件,该组件可以用来初始化一个项目, 即 按照一定的目录结构,生成一个新项目

(3)在你想创建项目的目录下  例如 D:/project/ 打开cmd命令 输入

create-react-app react-tutorial

去使用creat-react-app命令创建名字是react-tutorial的项目

安装完成后,移至新创建的目录并启动项目

cd react-tutorial
yarn start

一旦运行此命令,localhost:3000新的React应用程序将弹出一个新窗口。

项目目录结构

一个/public和/src目录,以及node_modules,.gitignore,README.md,和package.json。

在目录/public中,重要文件是index.html,其中一行代码最重要

    <div id="root"></div>

该div做为我们整个应用的挂载点

/src目录将包含我们所有的React代码。

要查看环境如何自动编译和更新您的React代码,请找到文件/src/App.js:

将其中的

        <a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>

修改为

        <a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
和豆约翰 Learn React
</a>

保存文件后,您会注意到localhost:3000编译并刷新了新数据。



现在删除/src目录中的所有文件,我们将从头开始创建自己的项目文件。

开始我们的mini项目

1.新建文件index.css

我们就拷贝index.css文件的全部内容(css不是我们这次课程的重点).

2.新建文件index.js

在index.js中,我们将导入React,ReactDOM和CSS文件。

src / index.js

import React, { Component }  from 'react'
import ReactDOM from 'react-dom'
import './index.css'

创建App组件,在render方法中返回一个div(这里是JSX语法)

src / index.js

class App extends Component {
render() {
return (
<div className="App">
<h1>Hello, React!</h1>
</div>
)
}
}

最后,我们将App渲染到根节点。

src / index.js

ReactDOM.render(<App />, document.getElementById('root'))

index.js完整代码

import React, { Component }  from 'react'
import ReactDOM from 'react-dom'
import './index.css' class App extends Component {
render() {
return (
<div className="App">
<h1>Hello, React!</h1>
</div>
)
}
} ReactDOM.render(<App />, document.getElementById('root'))

在浏览器输入localhost:3000,您将看到“你好,React!

JSX:JavaScript + XML

如您所见,我们在React代码中一直使用看起来像HTML的东西,但它并不是完全HTML。这是JSX,代表JavaScript XML。

使用JSX,我们可以编写看起来像HTML的内容,也可以创建和使用我们自己的类似XML的标签。

以下是JSX分配给变量的样子:

const heading = <h1 className="site-heading">Hello, React</h1>

编写React并非必须使用JSX。在幕后,它正在运行createElement,它接受标签,包含属性象和组件的后代,并呈现相同的信息。下面的代码将具有与上面的JSX相同的输出。

const heading = React.createElement('h1', { className: 'site-heading' }, 'Hello, React!')

JSX实际上更接近JavaScript,而不是HTML,因此在编写时需要注意一些关键区别。

  • className用于代替class添加CSS类(classJavaScript中的保留关键字)。
  • JSX中的属性和方法为camelCase(驼峰表示法) - onclick将变为onClick。
  • 自闭合标签必须以斜杠结尾-例如
  • JavaScript表达式也可以使用大括号(包括变量,函数和属性)嵌入JSX内。
const name = 'Tania'
const heading = <h1>Hello, {name}</h1>

JSX比在原生JavaScript中创建和添加元素更容易编写和理解,这也是人们如此热爱React的原因之一。

组件

到目前为止,我们已经创建了一个组件- App组件。React中的几乎所有内容都由组件组成,这些组件可以是类组件或简单组件。

大多数React应用程序都有许多小组件,所有内容都加载到主App组件中。

组件经常定义在单个js文件中,

接下来让我们更改项目。从index.js中删除App类:

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './index.css' ReactDOM.render(<App />, document.getElementById('root'))

我们将创建一个新文件App.js,并将组件放入其中。

import React, { Component } from 'react'

class App extends Component {
render() {
return (
<div className="App">
<h1>Hello, React!</h1>
</div>
)
}
} export default App

我们将组件导出为App并将其加载到中index.js。将组件分成文件不是强制性的,但是如果不这样做的话,应用程序将开始变得笨拙和混乱。

类组件

让我们创建另一个组件。我们将创建一个表格。制作Table.js,并用以下数据填充。

src / Table.js

import React, { Component } from 'react'

class Table extends Component {
render() {
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Job</th>
</tr>
</thead>
<tbody>
<tr>
<td>Charlie</td>
<td>Janitor</td>
</tr>
<tr>
<td>Mac</td>
<td>Bouncer</td>
</tr>
<tr>
<td>Dee</td>
<td>Aspiring actress</td>
</tr>
<tr>
<td>Dennis</td>
<td>Bartender</td>
</tr>
</tbody>
</table>
)
}
} export default Table

我们创建的该组件是一个自定义类组件。自定义组件名称首字母大写,以区别于常规HTML元素。回到App.js,我们可以先将表格组件导入,以加载表格组件:

src / App.js

import Table from './Table'

然后将其加载到App类的render()函数中,在此之前我们已经有了“ Hello,React!”。还更改了外部容器的类名。

import React, { Component } from 'react'
import Table from './Table' class App extends Component {
render() {
return (
<div className="container">
<Table />
</div>
)
}
} export default App

现在,我们已经了解了什么是自定义类组件。我们复用此组件。但是,由于数据已被硬编码到其中,因此目前它并不太有用。

简单组件

React中的另一种类型的组件是simple component,它是一个函数。该组件不使用class关键字。让我们为Table组件制作两个简单的子组件-一个表头和一个表主体。

我们将使用ES6箭头表达式来创建这些简单的组件。首先,表头:

src / Table.js

const TableHeader = () => {
return (
<thead>
<tr>
<th>Name</th>
<th>Job</th>
</tr>
</thead>
)
}

然后是表主体。

src / Table.js

const TableBody = () => {
return (
<tbody>
<tr>
<td>Charlie</td>
<td>Janitor</td>
</tr>
<tr>
<td>Mac</td>
<td>Bouncer</td>
</tr>
<tr>
<td>Dee</td>
<td>Aspiring actress</td>
</tr>
<tr>
<td>Dennis</td>
<td>Bartender</td>
</tr>
</tbody>
)
}

现在,我们的Table.js文件将如下所示。请注意,TableHeader和TableBody组件都在同一个文件中,并由Table类组件使用。

src / Table.js

import React, { Component } from 'react'

const TableHeader = () => {
return (
<thead>
<tr>
<th>Name</th>
<th>Job</th>
</tr>
</thead>
)
} const TableBody = () => {
return (
<tbody>
<tr>
<td>Charlie</td>
<td>Janitor</td>
</tr>
<tr>
<td>Mac</td>
<td>Bouncer</td>
</tr>
<tr>
<td>Dee</td>
<td>Aspiring actress</td>
</tr>
<tr>
<td>Dennis</td>
<td>Bartender</td>
</tr>
</tbody>
)
} class Table extends Component {
render() {
return (
<table>
<TableHeader />
<TableBody />
</table>
)
}
} export default Table

运行结果不变。如您所见,组件可以嵌套在其他组件中,并且简单和类组件可以混合使用。

一个类组件必须包含render(),并且return只能返回一个父元素。

作为总结,让我们比较一个简单的组件和一个类组件:.

简单组件

const SimpleComponent = () => {
return <div>Example</div>
}

类组件

class ClassComponent extends Component {
render() {
return <div>Example</div>
}
}

props

我们的Table组件,数据是硬编码的。关于React的重要问题之一是它如何处理数据,它使用属性(props)和状态(state)来处理数据。现在,我们将专注于使用props处理数据。

首先,让我们从TableBody组件中删除所有数据。

src / Table.js

const TableBody = () => {
return (
<tbody></tbody>
)
}

然后,将所有数据定义到一个对象数组中:

src / App.js

class App extends Component {
render() {
const characters = [
{
name: 'Charlie',
job: 'Janitor',
},
{
name: 'Mac',
job: 'Bouncer',
},
{
name: 'Dee',
job: 'Aspring actress',
},
{
name: 'Dennis',
job: 'Bartender',
},
] return (
<div className="container">
<Table />
</div>
)
}
}

接下来,我们将通过属性characterData将数据传递给子组件Table,传递的数据是characters变量,由于它是JavaScript表达式,因此使用大括号括起来。

return (
<div className="container">
<Table characterData={characters} />
</div>
)

现在数据已经传递到Table组件,我们可以在Table组件通过this.props中访问到。

src / Table.js

class Table extends Component {
render() {
const { characterData } = this.props return (
<table>
<TableHeader />
<TableBody characterData={characterData} />
</table>
)
}
}

由于Table组件实际上由两个较小的简单组件组成,因此再次通过props 将其传递给子组件TableBody

我们将把props作为参数传递给简单组件TableBody ,并通过数组的map方法将数据映射为jsx片段的集合。该jsx片段集合将包含在rows变量中,我们将其作为表达式返回。

const TableBody = props => {
const rows = props.characterData.map((row, index) => {
return (
<tr key={index}>
<td>{row.name}</td>
<td>{row.job}</td>
</tr>
)
}) return <tbody>{rows}</tbody>
}

您会注意到我已经向每个表行添加了一个键索引。在React中创建列表时,应始终使用键,因为它们有助于识别每个列表项。我们还将在需要操纵列表项的时刻看到这是必要的。

props是将现有数据传递到React组件的有效方法,但是该组件无法更改props-它们是只读的。在下一节中,我们将学习如何使用状态(state)来进一步控制React中的数据处理。

state

我们将表格数据存储在数组变量中,并将其作为props传递。但是如果我们希望能够从数组中删除一个项目,就做不到了。props,是一种单向数据流,子组件不能进行修改。但是有了state,我们就可以更新组件中的私有数据。

您可以将state视为可以在组件内增删改的而不必添加到数据库的任何临时数据-例如,在确认购买之前在购物车中添加和删除的购物车项目。state改变后,绑定state数据的视图会自动更新。

首先,我们将创建一个state对象。

src / App.js

class App extends Component {
state = {}
}

在state对象中定义属性,保存我们所需的数据。

src / App.js

class App extends Component {
state = {
characters: [],
}
}

将我们之前创建的对象的整个数组移到中state.characters。

class App extends Component {
state = {
characters : [
{
name: 'Charlie',
job: 'Janitor',
},
{
name: 'Mac',
job: 'Bouncer',
},
{
name: 'Dee',
job: 'Aspring actress',
},
{
name: 'Dennis',
job: 'Bartender',
},
]
}
}

在App.js中,创建removeCharacter方法来删除一个项目

removeCharacter = index => {
const { characters } = this.state this.setState({
characters: characters.filter((character, i) => {
return i !== index
}),
})
}

您必须使用this.setState()来修改数组。简单地将新值应用到this.state.property将不起作用。

现在,我们必须将该函数传递给组件。我们会将removeCharacter函数作为属性传递给Table。

src/App.js

render() {
const { characters } = this.state return (
<div className="container">
<Table characterData={characters} removeCharacter={this.removeCharacter} />
</div>
)
}

由于Table组件,并不需要自己的state数据对象,所以,我们将它改造成简单组件,并将removeCharacter函数继续向TableBody 子组件传递:

src/Table.js

const Table = props => {
const { characterData, removeCharacter } = props return (
<table>
<TableHeader />
<TableBody characterData={characterData} removeCharacter={removeCharacter} />
</table>
)
}

在TableBody组件中,我们将键/索引作为参数传递,因为removeCharacter函数知道要删除的项目索引。我们创建一个按钮并将其onClick事件绑定removeCharacter函数;

src/Table.js

<tr key={index}>
<td>{row.name}</td>
<td>{row.job}</td>
<td>
<button onClick={() => props.removeCharacter(index)}>Delete</button>
</td>
</tr>

onClick事件必须绑定为返回该removeCharacter()方法的函数,否则removeCharacter()将尝试不等按钮点击而自动运行。

新增表格数据

现在我们已经将数据存储在App.js组件的state对象中,并且可以从state对象中删除任何项目。但是,如何向state对象中添加数据呢?我们将通过一个表单组件来实现这个需求。

首先,state.characters中删除所有硬编码数据:

src / App.js

class App extends Component {
state = {
characters: [],
}
}

创建新文件Form.js。

import React, { Component } from 'react'

class Form extends Component {
initialState = {
name: '',
job: '',
} state = this.initialState
}

以前,React类组件有必要包括一个constructor(),但是现在不再需要。

此表单的目标是Form每次更改表单中的字段时都会更新本组件(Form)的state,并且在我们提交表单时,所有数据都将传递给App组件的state,然后Table组件会自动更新。

首先定义input控件的onChange事件处理函数:

src / Form.js

handleChange = event => {
const { name, value } = event.target this.setState({
[name]: value,
})
}

Form组件的render函数实现如下:

src / Form.js

render() {
const { name, job } = this.state; return (
<form>
<label htmlFor="name">Name</label>
<input
type="text"
name="name"
id="name"
value={name}
onChange={this.handleChange} />
<label htmlFor="job">Job</label>
<input
type="text"
name="job"
id="job"
value={job}
onChange={this.handleChange} />
</form>
);
} export default Form;

在App.js,导入Form:

import Form from './Form';

return (
<div className="container">
<Table characterData={characters} removeCharacter={this.removeCharacter} />
<Form />
</div>
)

最后一步是实现提交该数据并更新父组件状态。我们将创建一个名为handleSubmit()的函数,该函数将使用[ES6扩展运算符]语法来更新状态。

src / App.js

handleSubmit = character => {
this.setState({ characters: [...this.state.characters, character] })
}

确保我们将其作为参数传递给Form。

<Form handleSubmit={this.handleSubmit} />

现在,在Form中,我们将创建一个名为submitForm()的方法,该方法将调用传进来的handleSubmit函数,并将Form的state作为character参数传递。它还将Form的state重置为初始状态,以在表单提交后清除表单信息。

src / Form.js

submitForm = () => {
this.props.handleSubmit(this.state)
this.setState(this.initialState)
}

最后,我们将在Form.js中添加一个提交按钮以提交表单,点击将调用我们刚定义的submitForm函数。

src / Form.js

<input type="button" value="Submit" onClick={this.submitForm} />

就是这样!该应用程序已完成。

完整代码

一篇文章快速入门React框架的更多相关文章

  1. 快速入门react

    安装react npm install creat-react-app -g这里直接安装react的一个脚手架,里面包含了要用到的许多东西,帮助快速入门react 创建新项目 create-react ...

  2. 快速入门GreenDao框架并实现增删改查案例

    大家的项目中不可避免的使用到SQLite,为此我们要花费心思编写一个增删改查框架.而一个好的ORM框架则能够给我们带来极大的方便,今天给大家讲解一个非常火热的ORM-GreenDao. 基本概念 Gr ...

  3. 《Spring3.0就这么简单》第1章快速入门

    问题 [如何将jsp中传递到HttpServletRequest的参数,自动装配到Java对象中] [成功] public void setUsernAme(String username) < ...

  4. 【零基础】快速入门爬虫框架HtmlUnit

    迅速的HtmlUnit htmlunit是一款开源的web页面分析工具,理论上来说htmlunit应用于网页的自动化测试,但是相对来说更多人使用它来进行小型爬虫的快速开发.使用htmlunit进行爬虫 ...

  5. 《C++ 101条建议》学习笔记——第一章快速入门

    1.C++程序组成:a.编译指示,由#开始,不由分号结束.只是影响编译过程.b.声明语句,影响编译过程,编译结果中并不会生成对应的指令.只是告诉编译器一些信息.c.可执行过程语句,生成对应的指令.包括 ...

  6. 一篇文章快速搞懂 Atomic(原子整数/CAS/ABA/原子引用/原子数组/LongAdder)

    前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized,还有另一大分支Atomic.如果大家没听过没用过先看基础篇,如果听过用过,请滑至底部看进阶篇,深入 ...

  7. 一篇文章快速搞懂Qt文件读写操作

    导读:Qt当中使用QFile类对文件进行读写操作,对文本文件也可以与QTextStream一起使用,这样读写操作会更加简便.QFileInfo可以用来获取文件的信息.QDir可以用于对文件夹进行操作. ...

  8. 一文让你快速入门pytest框架

    pytest是什么 官方文档描述: pytest is a framework that makes building simple and scalable tests easy. Tests ar ...

  9. Android初级教程理论知识(第一章快速入门)

    一.综合介绍. Android项目的目录结构 Activity:应用被打开时显示的界面 src:项目代码 R.java:项目中所有资源文件的资源id Android.jar:Android的jar包, ...

随机推荐

  1. fakebook

    0x01 查看robots.txt 发现user.php.bak文件 得到源码 <?php class UserInfo { public $name = ""; publi ...

  2. android 动态设置TextView值,例:金额增加

    一说到动态递增设置TextView值,很多人应该马上就想到起个线程,让后在线程中睡眠指定时间,使用handler发送消息更新TextView值! 这样是实现了动态递增设置TextView值但是效率不咋 ...

  3. Jmeter参数化四种方式

    JMeter的三种参数化方式包括: 1.用户参数 2.函数助手 3.CSV Data Set Config/CSV数据配置文件 4.用户自定义变量 一.用户参数 位置:添加-前置处理器-用户参数 操作 ...

  4. PAT 1006 Sign In and Sign Out (25分) 字符串比较

    题目 At the beginning of every day, the first person who signs in the computer room will unlock the do ...

  5. 「雕爷学编程」Arduino动手做(26)——4X4矩阵键盘模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  6. Python list列表修改元素

    Python 提供了两种修改列表(list)元素的方法,你可以每次修改单个元素,也可以每次修改一组元素(多个). 修改单个元素 修改单个元素非常简单,直接对元素赋值即可.请看下面的例子: nums = ...

  7. spark机器学习从0到1奇异值分解-SVD (七)

      降维(Dimensionality Reduction) 是机器学习中的一种重要的特征处理手段,它可以减少计算过程中考虑到的随机变量(即特征)的个数,其被广泛应用于各种机器学习问题中,用于消除噪声 ...

  8. 11.3 Go 开发博客

    11.2 Go 开发博客 1.1. MVC模式 MVC分层简化了分组开发.不同的开发人员可同时开发视图,控制器逻辑和业务逻辑. 耦合性低:视图层和业务逻辑层分离.相互独立,不受影响 重用性高:业务逻辑 ...

  9. charme浏览器 jquery1.9.1min.js 报脚本错误 无jquery.min.map 文件

    http://www.vipaq.com/Article/View/blog/357.html /*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation ...

  10. spring——bean自动装配

    注意:自动装配功能和手动装配要是同时使用,那么自动装配就不起作用. beans.xml <?xml version="1.0" encoding="UTF-8&qu ...