内容简介:我一开始学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… 上了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java Web整合开发王者归来
刘京华 / 清华大学 / 2010-1 / 99.80元
《Java Web整合开发王者归来(JSP+Servlet+Struts+Hibernate+Spring)》全面介绍了Java Web开发中的各种相关技术及知识。全书分为9篇,内容层次清晰,难度循序渐进。第1篇为入门篇,内容包括Java Web开发概述等;第2篇为基础篇,内容包括Servlet技术、JSP技术、会话跟踪、过滤器Filter、监听器Listener等;第3篇为高级篇,内容包括JST......一起来看看 《Java Web整合开发王者归来》 这本书的介绍吧!