内容简介:我一开始学Javascript的时候就听说过React了,但是我得承认当我看了一眼React后,它吓到我了。我看到了一堆HTML混合着Javascript,然后我想,这不是我们努力避免的事情吗?React到底有什么大不了的?没有过多关注React,相反,我只是关注于学习VanilaJS(额,其实就是纯粹的原生JS,VanillaJs=Javascript)并在工作环境里使用Jquery。我几次想试图开始使用React,但是都失败了,最终我决定好好学习React,我开始去了解为什么我可能想要使用Reacte而
我一开始学Javascript的时候就听说过React了,但是我得承认当我看了一眼React后,它吓到我了。我看到了一堆HTML混合着Javascript,然后我想,这不是我们努力避免的事情吗?React到底有什么大不了的?
没有过多关注React,相反,我只是关注于学习VanilaJS(额,其实就是纯粹的原生JS,VanillaJs=Javascript)并在工作环境里使用Jquery。我几次想试图开始使用React,但是都失败了,最终我决定好好学习React,我开始去了解为什么我可能想要使用Reacte而不是原生的JS或是Jquery?
我尽力把所有我学过的东西压缩成了这一篇很好的导学教程,分享给大家,让我们开始。
先决条件
在开始玩React之前,有一些你必须提前知道的知识。如果你从来没有使用过Javascript或者是一点都不了解DOM,我建议在尝试学习React之前先熟悉这些内容。
以下是我认为的学习React的先决条件:
- 基本熟悉HTML 和 CSS
- 基本掌握 Javascript编程
- 基本理解 DOM
- 熟悉ES6的语法与特性
- Nodejs 和 npm 全局安装
目标
- 学习React重要的概念和相关的技术,比如,Babel,Webpack,JSX,components,props,state 和 lifecycle
- 构建一个简单的react-app来演示上面的那些概念
下面是源代码和最终结果的真实demo
什么是React?
- React是一个Github上最流行的JS库之一,有超过100000个Star
- React并不是一个框架(不像Angular)
- React是一个由Facebook创建的开源项目
- React用来构建前端UI
- React是MVC应用的View层
在React中最重要的一个方面就是你可以像创建HTML元素一样创建自定义可重用的组件,来快速高效的构建UI。同时,React可以使用 state 和 props 特性来简化数据的存储和处理流程。
我们会在这篇文章中讲解这些甚至是更多,所以让我们开始。
开始和安装
有很多方法可以开始使用React,这里我只展示两种方法,以便你可以搞清楚如何启动一个react。
静态HTML文件
第一个启动React的方法不是很流行,和我们之后教程里的做法也不相同,但是如果你熟悉像Jquery这样的库,这个方法会更熟悉更容易理解。如果你不熟悉Webpack,Babel和Nodejs,那这个方法是代价最小的方法了
我们先创建一个基本的 index.html 文件,然后我们在 head 头部加入这三个CDN——React,React DOM和Babel。同时创建一个id为 root 的 div 标签,最后我们创建 script 标签来放我们要写的React代码
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello React!</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// React code will go here
</script>
</body>
</html>
复制代码
我加载的CDN是写这篇文章时最新的稳定版本
- React —— React顶层API
- React DOM —— 添加DOM专用的方法
- Babel —— 一个可以让我们在浏览器使用ES6+的JS编译器
我们应用的入口就是那个id为 root 的div元素,命名为 root 只是一种习惯上的命名,你完全可以命名为其他的。你可能注意到了 script 标签中的类型是 text/babel ,这是强制使用babel的意思。
现在,我们来写我们的第一段React代码片。我们将用ES6的类来创建一个叫App的React组件。
class App extends React.Component {
//...
}
复制代码
然后我们为其添加一个 render() 方法,这个方法是一个类组件中唯一必要的方法,用以渲染DOM节点。
class App extends React.Component {
render() {
return (
//...
);
}
}
复制代码
在 return 中,我们将写入一些看起来就像HTML元素的东西。值得注意的是,我们这里返回的不是字符串,所以不用在内容里加入引号。这种写法叫做 JSX ,我们稍后就会学到它。
class App extends React.Component {
render() {
return <h1>Hello world!</h1>
}
}
复制代码
最后,我们将使用React DOM的 render() 方法把我们在 root 节点上创建的 App 类组件渲染出来。
ReactDOM.render(<App />, document.getElementById('root'))
复制代码
下面是 index.html 的全部内容
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello React!</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component {
render() {
return <h1>Hello world!</h1>
}
}
ReactDOM.render(<App />, document.getElementById('root'))
</script>
</body>
</html>
复制代码
现在,如果你在浏览器看你的渲染结果,你可以看到 h1 标签已经被渲染出来了
太酷了!想必你做到这里,可以看出开始使用React并不是像想象中的那样令人畏惧。他只不过是一些我们可以加载到HTML中的JavaScript帮助库罢了。
以上我们做的都是为了演示目的,但是从这里开始我们将使用另一种方法:Create React App。
Create React App
在静态文件里加载Javascript库,渲染React并实时Babel编译的方法是很不高效且难以维护。
幸运的是,Facebook创造了 Create React App ,一个预先配置好了所有在构建React应用时所需的的环境。它会创建一个实时的开发服务器,使用webpack自动编译React、JSX和ES6,自动添加CSS文件前缀,并且使用ESlint测试和警告代码中的错误。
要启动Create-react-app,你需要在你的终端运行以下代码,一个新的目录会被创建到当前目录下。请确保你有5.2或者更高版本的Nodejs环境。
npx create-react-app react-tutorial 复制代码
一旦完成安装,移动到新建的目录里并启动项目。
cd react-tutorial npm start 复制代码
执行完上面的命令,浏览器会弹出新窗口,并用 localhost:3000 服务你的新建的React应用。
如果你去看项目结构,你会看到 /public 和 /src 目录,以及我们常看到的 node_modules 、 .gitgnore 、 README.md 和 package.json 。
在 /public 目录下,最重要的文件就是 index.html ,这个我们之前创建的静态 index.html 是类似的,只有一个 root div。但是这次,没有任何库文件或者是 script 标签被引入。 /src 目录下将包含所有我们需要的React代码。
想要看环境是如何自动化编译和更新你的React代码的,你可以去在 /src/App.js 中找下面这行。
To get started, edit `src/App.js` and save to reload. 复制代码
然后用其他任何文本替换它。一旦你保存文件,你会发现 localhost:3000 编译并用新数据刷新了页面
继续,我们删除 /src 目录下的所有文件,我们将创建我们自己的模板文件。我们将仅保留 index.css 和 index.js
对于 index.css ,我只是复制粘贴了Primitive CSS中的内容。当然你也可以使用Bootstrap或者任何你想使用的CSS框架,又或者什么也不写。我只是为了更方便的讲解。
现在在 index.js 中,我们导入React、ReactDOM和CSS文件。
src/index.js
import React from 'react' import ReactDOM from 'react-dom' import './index.css' 复制代码
让我们再次创建我们的 App 组件。之前,我们只有 <h1> ,但是现在我们把它添加进一个带有 class 属性的div元素中。你会发现我们使用了 ClassName 而不是 class 。这是给我们的第一个暗示表明了这里所写的代码是Javascript,而不是真实的HTML
class App extends Component {
render() {
return (
<div className="App">
<h1>Hello, React!</h1>
</div>
)
}
}
复制代码
最终,我们会像之前那样渲染 App 到根节点去
ReactDOM.render(<App />, document.getElementById('root'))
复制代码
下面是整个 index.js 文件。这次,我们将 Component 作为React的一个属性加载,所以我们不用在继承自 React.Component
src/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 ,你可以看到"Hello,React!",就像之前那样。我们现在开始使用React应用了。
React Developer Tools
有一个插件叫React Developer Tools , 可以让你更简单的玩React。下载 React DevTools for Chrome ,或者其他任何你喜欢的浏览器对应的插件。
安装完后,当你打开DevTools时,你会看到一个React专门的标签栏。点击他,你就可以检查你之前写的组件,但这并不妨碍你去 Element 标签栏看真实的DOM输出。目前你似乎看不出来这有什么大不了的,但是当这个应用编译的内容越来越多的时候,这个插件就显得极为必要。
现在我们准备好了所有的 工具 和配置,我们需要真的开始学习React了。
JSX:JavaScript + XML
如你所见,我们正在使用看起来像HTML的代码构建React组件,但是他不是真正的HTML。那是 JSX ,是JavaScript XML的缩写。
使用JSX,我们可以像HTML那样书写,也可以创建和使用我们自己的类XML标签。下面是将JSX赋给一个变量。
JSX
const heading = <h1 className="site-heading">Hello, React</h1> 复制代码
写React并不强制使用JSX。深入原理,React执行的其实是 createElement ,通过这个方法传入标签、包含属性的对象,以及子组件这些参数,并渲染,可以得到相同的结果。下面的代码的输出等同于上面JSX。
Non-JSX
const heading = React.createElement('h1', { className: 'site-heading' }, 'Hello, React!')
复制代码
JSX事实上更接近与Javascript,而不是HTML,所以这里有一些书写时需要注意的重要的区别。
- 因为
class是Javascript中的预留关键字,所以ClassName用来代替class添加CSS类名 - 在JSX里,属性和方法都是驼峰法命名的,比如,
onclick将会变成onClick - 自关闭标签必须以斜线结尾,比如,
<img />
通过使用大括号,JavaScript表达式也可以嵌入JSX中,包括变量,函数和属性。
const name = 'Tania'
const heading = <h1>Hello, {name}</h1>
复制代码
比起用原生JS创建和添加许多元素,JSX更容易书写,并且好理解,这也是人们钟爱React的一个原因。
Components
目前为止,我们创建了一个组件—— App 组件。在React中,几乎所有的东西都是由组件组成,组件分为两种, class component 和 simple component 。
大部分React应用都有很多小的组件,然后把所有东西都加载到一个主 App 组件中去。组件通常都有自己一个单独的文件,所以让我们改变我们的项目做到这一点。
从 index.js 中删除 App 类,就像这样
src/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 的文件,然后把 App 组件搬到这里
src/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 中加载它。这样把组件分隔到一个单独文件的做法不是强制的,但是如果你不这样做,应用将会变得笨重且难以控制。
Class Components
让我们再创建一个组件。我们将创建一个表格。新建 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 ,我们可以加载Table组件,首先像这样导入:
import Table from './Table' 复制代码
然后在 App 的 render() 函数中加载它,就是之前我们写"Hello,React!"的地方。我也把外面的div的类名改为container
return (
<div className="container">
<Table />
</div>
)
复制代码
回去查看浏览器,你可以看到 Table 加载出来了
现在你看到了什么是一个自定义的类组件。我们可以无数次地复用这个组件。然而,因为数据是硬编码进去的,这个组件现在可用性较差。
Simple Components
另一种书写React组件的方法是simple component,它是一个函数。这个组件书写方式并不使用 class 关键字。让我们把 Table 组件分成两个simple component——一个表头,一个表体
我们将使用ES6的箭头函数来创建这些simple component。首先是表头,
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>
)
}
复制代码
现在我们的 Table 类看起来是这样的
class Table extends Component {
render() {
return (
<table>
<TableHeader />
<TableBody />
</table>
)
}
}
复制代码
一切都可以像之前那样显示出来,你可以在浏览器中看到和之前一样的表格。如你所见,组件可以嵌入另一个组件,且simple component 和 class component可以混合使用。
一个类组件必须包含 render() ,且 return 只能返回一个父元素(也即根节点只能有一个)
做个总结,我们来对比一下simple component和class component。
Simple Component
const SimpleComponent = () => {
return <div>Example</div>
}
复制代码
Class Component
class ClassComponent extends Component {
render() {
return <div>Example</div>
}
}
复制代码
需要注意的是如果 return 只有一行,那么不需要括号。
Props
目前为止,我们拥有一个很酷的 Table 组件,但是数据是硬编码的。React其中一个了不起的地方就是他处理数据的方式,它使用属性( props )和状态( state )来处理数据。我们先关注如何使用props处理数据。
首先,删除 TableBody 里的所有数据
Table.js
const TableBody = () => {
return <tbody />
}
复制代码
然后我们把数据移入到一个数组对象中去,就好像我们引入了一个基于JSON的API。我们必须在我们的 render() 中创建这个数组
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>
)
}
}
复制代码
现在我们将通过属性传递这些数据给子组件(Table),这有点像你通过 data-attributes 的方式传递数据。我们可以给这个属性起任何名字,只要它不是预留的关键字即可,因此我给他命名为 characterData 。我要传递的数据是 characters 变量,且我会用大括号包含它,因它属于JS表达式。
return (
<div className="container">
<Table characterData={characters} />
</div>
)
复制代码
现在数据正传递给 Table ,我们必须在另一边接受它。
Table.js
class Table extends Component {
render() {
const { characterData } = this.props
return (
<table>
<TableHeader />
<TableBody characterData={characterData} />
</table>
)
}
}
复制代码
如果你打开React DevTools并检查 Table 组件,你会发现在属性中出现了这个数组。存储这里的数据就是广为人知的VirtualDOM,一个更快更高效的同步数据与实际DOM的方法。
这里的数据还不是真实的DOM。在 Table 中,我们可以通过 this.props 接受所有的props。我们这里只传递了一个props——characterData,所以我们使用 this.props.characterData 来取回数据
const { characterData } = this.props
复制代码
因为 Table 组件实际上由两个小的simple component组成,所以我们再次通过props将数据传递给 TableBody 。
Table.js
class Table extends Component {
render() {
const { characterData } = this.props
return (
<table>
<TableHeader />
<TableBody characterData={characterData} />
</table>
)
}
}
复制代码
到这里, TableBody 函数没有任何参数,且仅是返回一个标签。
const TableBody = () => {
return <tbody />
}
复制代码
我们将传递props作为函数参数,并通过Array.map方法来为数组中每一个对象返回一个表项。这个映射后的数组赋给 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>
}
复制代码
如果你去看应用的页面,所有的数据都已经加载出来了。
你可能注意到我为每一个表项加入了一个key(index)。当你在React中构建列表时,你应该总是使用key,因为这些key可以帮助标识每一个表项。等会当我们想要操纵表项时,我们就知道他的必要性了。
Props是一种高效的方式传递已存在的数据给React组件,但是组件并不能改变props——他们是只读的。在下一章节中,我们将学习如何使用state来实现在数据处理中更多的控制力。
State
目前为止,我们将character数据存入一个数组变量,并通过props传递它。这是一个好的开始,但是想象一下如果我们需要从数组中删除一项,使用props,我们只有单向数据流,但是使用state我们可以从组件中更新私有数据。
我们可以把state看作是那些需要保存和修改但是不需要添加至数据库的任何数据。举个例子,再确认购买之前从购物车中添加或删除一项,就是state的场景。
一开始,我们先来创建一个state对象
class App extends Component {
state = {}
}
复制代码
这个对象将包含所有你想存储在state中的属性。对我们而言,这个属性是 character 。
class App extends Component {
state = {
characters: [],
}
}
复制代码
把我们之前创建的完整数组对象移到 state.characters 中去
class App extends Component {
state = {
characters: [
{
name: 'Charlie',
// the rest of the data
},
],
}
}
复制代码
我们的数据现在正式包含在了state中。由于我们想要从表格中删除一个项character,我们现在将要在 App 类内创建一个 removeCharacter 方法。
为了取得state,我们使用和之前一样的ES6语法 this.state.characters 。为了更新state,我们将使用 this.setState() ,这是一个为了控制state而内置的方法。我们将基于之前传递的 index 来过滤数组,并返回过滤后的新数组。
你必须使用 this.setState() 来修改数组。简单的把一个新值赋给 this.state.property 是没有用的
App.js
removeCharacter = index => {
const { characters } = this.state
this.setState({
characters: characters.filter((character, i) => {
return i !== index
}),
})
}
复制代码
filter 并不会变异而是创建了一个新数组,是在JS中修改数组的首选方式。这一方法用传入的index对比数组中所有下标,返回除了index对应的项以外的其他所有的项。
现在我们必须传递这个函数到组件中去,并且在每个表项旁渲染一个button以便触发此函数。我们将 removeCharacter 作为一个prop传递给 Table 。
App.js
return (
<div className="container">
<Table characterData={characters} removeCharacter={this.removeCharacter} />
</div>
)
复制代码
不要忘了写 const { character } = this.state 来从state中获取正确的数据。
我们还要把它再次作为prop从 Table 传递给 TableBody 。
Table.js
class Table extends Component {
render() {
const { characterData, removeCharacter } = this.props
return (
<table>
<TableHeader />
<TableBody characterData={characterData} removeCharacter={removeCharacter} />
</table>
)
}
}
复制代码
下面就是我们在 removeCharater() 定义的index的出处。在 TableBody 组件里,我们把key/index作为参数传递,以致于过滤函数可以知道那一项需要被删除。我们将创建一个button并监听 onClick 事件,并将index传递过去。
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 的函数,否则它就会尝试自动运行(而不是触发运行)
真棒!我们现在已经有了删除按钮,我们可以通过删除一项来修改我们的state了
我这里删除了Mac
现在你应该理解state是如何初始化和被修改的了吧
提交表单数据
现在数据存储在state中,我们可以从中随意删除任何一项。但是,要是我们想要添加新的数据到state中去呢?在真实的应用中,更可能的情况是一开始只是空的state,然后添加进东西,就像待办清单或是购物车一样。
在开始之前,我们删除掉 state.characters 中所有硬编码的数据,因为我们现在需要通过表单来更新state
class App extends Component {
state = {
characters: [],
}
}
复制代码
创建一个 Form.js 的新文件,并在文件里创建 Form 组件。我们将创建一个类组件,并在类中使用 constructor() ,这是我们至今还未提到过的。我们需要 constructor() 来使用 this 和接受父组件属性
我们将设置 Form 的初始state为一个空的对象,然后将其赋给 this.state 。
Form.js
import React, { Component } from 'react'
class Form extends Component {
constructor(props) {
super(props)
this.initialState = {
name: '',
job: '',
}
this.state = this.initialState
}
}
复制代码
这个表单的目标是每当表单中文本域发生改变时就更新 Form 的state,然后,当我们提交时,所有数据都会传递给 App 的state,这样就会引起 Table 的更新
首先,我们创建一个函数,这个函数会在每次输入改变时执行。event对象将会被传递进去,我们可以由此来获取输入的 name(key) 和 value ,进而设置 Form 的state
handleChange = event => {
const { name, value } = event.target
this.setState({
[name]: value,
})
}
复制代码
在我们能提交表单之前,我们先完成这个功能。在render函数里,可以从state中获取我们需要的两个属性,并把他们作为值赋给对应的表单。我们在input上监听 onChange ,把 handleChange() 作为监听函数。最后导出我们的 Form 组件。
render() {
const { name, job } = this.state;
return (
<form>
<label>Name</label>
<input
type="text"
name="name"
value={name}
onChange={this.handleChange} />
<label>Job</label>
<input
type="text"
name="job"
value={job}
onChange={this.handleChange} />
</form>
);
}
export default Form;
复制代码
在 App.js 里,我们可以在表格下面渲染这个表单
App.js
return (
<div className="container">
<Table characterData={characters} removeCharacter={this.removeCharacter} />
<Form />
</div>
)
复制代码
现在再去看看你的应用页面,你会看到一个还未提交的表单。更新文本域的内容,你会看到 Form 本地state的变化
很酷吧!最后一步就是要真的可以提交数据并更新父state。我们将在 App 类内创建一个 handleSubmit() 函数,这个函数将使用扩展运算符(...)来把已存在的 this.state.character 和新添加的 character 参数铺平为一维数组进而更新state。
App.js
handleSubmit = character => {
this.setState({ characters: [...this.state.characters, character] })
}
复制代码
我们得确保这个函数传递给了 Form
<Form handleSubmit={this.handleSubmit} />
复制代码
现在在 Form 中,我们创建一个 submitForm() 的函数,用来调用 handleSubmit() 并将 Form 的state作为 handleSubmit() 的参数传递。再提交表单后,重置Form的state为初始化状态。
Form.js
submitForm = () => {
this.props.handleSubmit(this.state)
this.setState(this.initialState)
}
复制代码
最后我们在添加一个提交按钮来提交表单。我们用了 onClick 而不是 onSubmit ,是因为我们没有使用标准的提交功能。这个点击事件将会调用 submitForm 来完成功能。
<input type="button" value="Submit" onClick={this.submitForm} />
复制代码
完成了!我们可以从列表中创建,添加和删除用户。只要 Table 和 TableBody 已经从state拉取到数据,那么他就可以正确的展示出来。
如果你在那个地方不明白了,你可以看 GitHub上的完整源码
拉取API中的数据
React其中一个很常用的用法是从API中拉取数据。如果你尚不熟悉什么是API或者是如何连接一个API的话,我建议你读 How to Connect to an API with JavaScript ,这篇文章会带你浏览什么是API,以及如何在原生JS中使用他们
做一个小测试,我们可以创建一个 API.js 文件,并在里面创建一个新 App 组件。我们可以测试一个公共API——Wikipedia(需翻墙,你可以自己写一个后端API服务做测试)。你可以点入链接去查看API——确保你的浏览器安装有JSONView。
我们将使用JS内置的 Fetch 方法从URL端点获取数据并展示出来。通过改变 index.js 中的导入文件—— import App from './Api' ,你把之前的应用切换到测试文件。
我不打算再一行一行的解释代码了,因为我们已经学习了创建组件,渲染函数和state数组映射。这段代码新的部分就是 componentDidMount() ,这是React的一个生命周期函数。生命周期就是React里方法调用的顺序。 Mounting 指的是一个元素插入到DOM里的时候。
当我们从API中拉取数据时,我们希望使用 componentDidMount ,因为我们希望确保在我们拿到数据之前组件就已经渲染到DOM上了。在下面的代码片中,你会看到我们是如何从Wikipedia API中获取数据并展示到页面上的。
import React, { Component } from 'react'
class App extends Component {
state = {
data: [],
}
// Code is invoked after the component is mounted/inserted into the DOM tree.
componentDidMount() {
const url =
'https://en.wikipedia.org/w/api.php?action=opensearch&search=Seona+Dancing&format=json&origin=*'
fetch(url)
.then(result => result.json())
.then(result => {
this.setState({
data: result,
})
})
}
render() {
const { data } = this.state
const result = data.map((entry, index) => {
return <li key={index}>{entry}</li>
})
return <ul>{result}</ul>
}
}
export default App
复制代码
一旦保存并运行此文件,你就可以看到Wikipedia API的数据展示到了页面上
当然还有其他的一些生命周期函数,但是讲解那些超出了本篇文章的范围。你可以参阅React Components 来了解更多
构建并部署一个React应用
目前为止,我们所作的一切都是在开发环境中进行的。我们实时地编译,热重载和更新。对于生产环境来说,我们更希望加载静态文件——而不是源代码。我们可以通过构建和部署做到这一点。
现在,如果你只是想编译所有React代码并把他放到根目录的某个地方的话,你只需要运行下面这样命令:
npm run build 复制代码
这个命令将会创建一个包含你的应用的 build 文件夹。把这文件夹中的内容放到任何地方就行了。
你也可以再做点更厉害的,去用npm部署他。我们将构建一个Github主页,所以你需要熟悉Git和如何把你代码上传到Github。
确保你已经离开本地React环境了,所以目前代码不能运行。首先,我们要在 package.json 中添加一个 homepage 域,写入我们想要应用运作的URL地址。
"homepage": "https://taniarascia.github.io/react-tutorial", 复制代码
我们还需要添加下面两行到 scripts 字段
"scripts": {
// ...
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
}
复制代码
在你的项目里,你要添加 gh-pages 到 devDependencies
npm install --save-dev gh-pages 复制代码
然后构建项目,我们就可以得到所有编译后静态的文件
npm run build 复制代码
最后,我们部署到 gh-pages
npm run deploy 复制代码
全部完成了!这个应用现在可以运行在 taniarascia.github.io/react-tutor… 上了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Mastering Regular Expressions, Second Edition
Jeffrey E F Friedl / O'Reilly Media / 2002-07-15 / USD 39.95
Regular expressions are an extremely powerful tool for manipulating text and data. They have spread like wildfire in recent years, now offered as standard features in Perl, Java, VB.NET and C# (and an......一起来看看 《Mastering Regular Expressions, Second Edition》 这本书的介绍吧!