当我刚开始学习JavaScript
的时候,我就听说了React
,但我承认看了它一眼,它吓到我了。我看到了看起来一堆HTML
和CSS
的混合思想,这不是我们一直努力避免的事情吗?React有什么了不起的?
相反,我只专注于学习原始的JavaScript
,并在需要的时候使用jQuery
。经过几次失败的React
入门尝试之后,我终于开始了解它了,我开始明白为什么我可能想使用React
而不是原始的JS
或jQuery
。
我试图将自己学到的内容浓缩成一个很好的介绍,以便与你分享,下面就是~
预备知识
在开始学习React
之前,你应该事先了解一些事情。例如,如果你之前从没接触过JavaScript
或者DOM
,那么在解决React
之前,你要更加熟悉它们。
下面是我认为学习React
的预备知识:
- 熟悉 HTML & CSS的基础知识
- JavaScript 和编程的基础知识
- 对DOM有基本了解
- 熟悉 ES6 语法和特性
- 全局安装了Node.js 和 npm
目标
- 了解基本的
React
概念和相关术语,例如Babel
,Webpack
,JSX
,组件,属性,状态和生命周期 - 通过构建一个非常简单的
React
应用程序,以演示上面的概念。
下面是最终的相关源代码和示例。
React是什么?
React
是一个JavaScript
库 - 最受欢迎的库之一,在GitHub上超过100,000星星。React
不是一个框架(不像Angular
,定位是框架)。React
是Facebook
的开源项目。React
用于在前端构建用户界面UI
。React
是MVC (Model View Controller)
应用的View
层。
React
的最重要的方面之一是可以创建类似于自定义、可复用的HTML
元素的组件,以快速有效地构建用户界面。React
还使用状态state和属性props来简化数据的存储和处理方式。
我们将在本文中介绍这些内容及其更多的内容,我们来开始吧。
安装
有几种安装React
的方法,我将向你展示两种,以便你更好地了解它地工作方式。
静态HTML文件
第一种方法不是安装React
的流行方法,也不是我们本教程其余部分的工作方式,但是如果你接触过jQuery
之类的库,这将很熟悉并易于理解。如果你不熟悉Webpack
,Babel
和Node.js
,那这将是种恐怖的入门方式。
让我们开始创建一个基本的index.html
文件。我们将在头部head
中加载三个CDN
资源 - React
,DOM
和Babel
。我们还将创建一个id
为root
的div
,最后,我们将创建一个脚本script
标签,你自定义的代码将存在于该标签中。
# 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> 复制代码
在编写本文的时,我加载的库是稳定版本的。
我们应用程序的入口点是root div
元素,该元素按惯例命名。你还会注意到text / babel
的脚本类型,这是使用Babel
所必需的。
现在,让我们编写React
的第一个模块代码。我们将使用ES6
类来创建一个名为App
的React
组件。
# index.html class App extends React.Component { //... } 复制代码
现在,我们将添加render()
方法,这是类组件中唯一需要的方法,用于渲染DOM
节点。
# index.html class App extends React.Component { render() { return ( //... ); } } 复制代码
在return
内部,我们将编写简单的看起来像HTML
元素的内容。请注意,我们不在此处返回字符串,因此请勿在元素周围使用引号。这称为JSX
,我们将很快对其进行详细了解。
# index.html class App extends React.Component { render() { return <h1>Hello world!</h1> } } 复制代码
最后,我们将使用React DOM
的render()
方法将我们创建的App
类渲染到HTML
的root
容器div
中。
# index.html 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> 复制代码
现在,如果你在浏览器上查看index.html
,将看到我们创建的呈现给DOM
的h1
标签。
太棒了!现在你完成了这一步,你可以看到React
并没有那么让人着迷。只是一些JavaScript
帮助教程库,我们将其加载到HTML
中。
我们出于演示目的完成了此操作,但是从这里开始,我们将使用另一种方式:Create React App
。
创建React App
我刚刚使用的是将JavaScript
库加载到静态HTML
页面中并动态渲染React
和Babel
的方法不是很有效,并很难维护。
幸运的是,Facebook
创建了Create React App,该环境预先配置了构建React
所需要的一切。它将创建一个实时开发服务器,使用webpack
自动编译React
,JSX
和ES6
,自动为CSS
文件加前缀,并使用ESLint
测试和警告代码中的错误。
要设置create-react-app
,你要在终端运行以下代码,该代码位于你希望项目所在的目录。请确保你安装了5.2
以上版本的Node.js
。
npx create-react-app react-tutorial 复制代码
安装完成之后,移至新创建的目录并启动项目。
cd react-tutorial npm start 复制代码
运行此命令之后,新的React
应用程序将在浏览器的localhost:3000
弹出一个新窗口。
如果你查看项目结构,将会看到/public
和/src
目录,以及常规的node_modules
,.gitignore
,README.md
和package.json
。
在/public
中,我们的重要文件是index.html
,它与我们之前制作的静态index.html
文件非常类似 - 只是一个root div
。这次,没有库或脚本被加载。/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>
,但是现在我还要添加一个带有类的div
元素。你会注意到,我们使用的是className
而不是class
。这是我们的第一个提示,此处编写的代码是JavaScript
,而不是HTML
。
# 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
代码。这次,我们将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开发者工具
有一个名为React Developer Tools
的扩展工具,可以使你在使用React
时的工作更加轻松。在你喜欢使用的任何浏览器中下载 React DevTools for Chrome。
安装后,当你打开DevTools
时,你将看到React
的标签。单击它,你将能够在编写组件时检查它们。你仍然可以转到elements
选项卡以查看实际的DOM
输出。现在看来似乎没什么大不了的,但是随着应用程序变得越来越复杂,使用它的必要性将越来越明显。
现在,我们拥有了实际开始使用React
所需的所有工具和安装设置。
JSX: JavaScript + XML
正如你所见,我们在React
代码中一直使用看起来像HTML
的东西,但是它并不是完全的HTML
。这是JSX,代表JavaScript XML
。
使用JSX
,我们可以编写类似HTML
的内容,也可以创建和使用自己的类似XML
的标签。下面是JSX
赋值给变量的样子。
# JSX const heading = <h1 className="site-heading">Hello, React</h1> 复制代码
编写React
并非必须使用JSX
。它在后台运行createElement
,它使用标签,包含属性的对象和子组件并呈现相同的信息。
下面的代码具有和上面使用JSX
语法相同的输出。
# No 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> 复制代码
JSX
比原始的JavaScript
中创建和添加许多元素更容易编写和理解,这也是人们如此热爱React
的原因之一。
组件
到目前为止,我们创建了一个组件 - App
组件。React
中几乎所有内容都由组件组成,这些组件可以是类组件或简单组件。
大多数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
的新文件,然后将组件放在那里。
# 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
中。将组件分成文件不是强制性的,但是如果不这样做的话,应用程序将变得笨拙和混乱。
类组件
让我们创建另一个组件。我们将创建一个表格。创建一个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
导入到其中:
# src/App.js import Table from './Table' 复制代码
然后通过将其加载到App
的render()
中,然后获得Hello, React!
。我还更改了外部容器的类。
# src/App.js import React, { Component } from 'react' import Table from './Table' class App extends Component { render() { return ( <div className="container"> <Table /> </div> ) } } export default App 复制代码
如果你重新查看实际环境,则会看到Table
已加载。
现在,我们了解了什么是自定义类组件。我们可以反复使用此组件。但是,由于将数据硬编程(即写死)在其中,因此目前它并不太实用。
简单组件
React
中另外一种类型的组件就是简单组件,它是一个函数。该组件不使用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
文件如下所示。请注意,TableHeader
和TableBody
组件都在同一个文件中,并且由Table
类组件使用。
# src/Table.js const TableHeader = () => { ... } const TableBody = () => { ... } class Table extends Component { render() { return ( <table> <TableHeader /> <TableBody /> </table> ) } } 复制代码
之后,一切都像之前那样展示。如你所见,组件可以嵌套在其他组件中,并且简单组件和类组件可以混合使用。
一个类组件必须包括 render(),并且返回只能返回一个父组件。
作为总结,让我们来比较一个简单组件和一个类组件。
# 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
组件的数据移除。
# src/Table.js const TableBody = () => { return <tbody /> } 复制代码
然后,将所有数据移到对象数组中,就像我们引入基于JSON
的API
一样。我们必须在render()
内部创建此数组。
# 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> ) } } 复制代码
现在,我们将通过属性将数据传递给子组件(Table
),这类似于使用数据data-
属性传递数据的方式。只要不是保留关键字,我们都可以随意调用该属性,因此我将使用characterData
。我传递的数据是Characters
变量,由于它是JavaScript
表达式,因此用大括号括起来。
# src/App.js return ( <div className="container"> <Table characterData={characters} /> </div> ) 复制代码
现在,数据已经传递给Table
,我们要做得是在另一边接收数据。
# src/Table.js class Table extends Component { render() { const { characterData } = this.props return ( <table> <TableHeader /> <TableBody characterData={characterData} /> </table> ) } } 复制代码
如果你打开React DevTools
,然后观测Table
组件,你将看到一个数组数据在其属性上。此处存储的数据称为虚拟DOM,这是一种将数据与实际DOM
同步快速有效的方法。
但是,此数据尚未在实际的DOM
中。在表格中,我们可以通过this.props
访问所有属性。我们仅传递一个属性characterData
,因此我们将使用this.props.characterData
来检索该数据。
我将使用ES6
属性的简写来创建一个包含this.props.characterData
的变量。
const { characterData } = this.props 复制代码
因为,我们的Table
组件实际上由两个小的简单组件组成,因此我将再次通过props
将其传递给TableBody
。
# src/Table.js class Table extends Component { render() { const { characterData } = this.props return ( <table> <TableHeader /> <TableBody characterData={characterData} /> </table> ) } } 复制代码
现在,TableBody
不带任何参数并返回单个标签。
# src/Table.js const TableBody = () => { return <tbody /> } 复制代码
我们将把props
作为参数传递,并通过map返回数组中每个对象的表行。该映射(map)将包含在rows
变量中,我们将其作为表达式返回。
# src/Table.js 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
中创建列表时,应始终使用key(键),因为它们有助于识别每个列表项。我们还将在需要操纵列表项的时刻看到这是必要的。
Props
是将现有数据传递到React
组件的有效方法,但是该组件无法更改属性 - 它们是只读的。在下一节中,我们将学习如何使用state
来进一步控制React
中的数据处理。
state状态
现在,我们将字符数据存在变量的数组中,并将其作为props
传递。这是一个很好的开始,但是请想象下,如果我们希望能够从数组中删除一个项目。使用props
,我们有了一种单向数据流;但是有了状态state
,我们可以更新组件中的私有数据。
你可以将状态state
视为无需保存或修改,而不必添加到数据库中的任何数据 - 例如,在确认购买之前,在购物车中添加和删除商品。
首先,我们将创建一个状态state
对象。
# src/App.js class App extends Component { state = {} } 复制代码
该对象将包含你需要在状态中存储的所有内容属性。对我们来说,就是characters
。
# src/App.js class App extends Component { state = { characters: [], } } 复制代码
将我们之前创建的对象的整个数组移到state.characters
中。
# src/App.js class App extends Component { state = { characters: [ { name: 'Charlie', // the rest of the data }, ], } } 复制代码
我们的数据已正式包含在state
中。由于我们希望能够从表格中删除字符,因此我们将父App
类上创建removeCharacter
方法。
要检索状态,我们将使用与以前相同的ES6
方法获取this.state.characters
。要更新这个状态,我们使用this.setState()
,这是一种用于处理状态state
的内置方法。我们将根据传递的索引index
过滤filter数组,然后返回新数组。
你必须使用 this.setState() 修改数组。仅将新值应用于 this.state.propert 将不起作用
# src/App.js removeCharacter = index => { const { characters } = this.state this.setState({ characters: characters.filter((character, i) => { return i !== index }), }) } 复制代码
filter
不会突变,而是创建一个新数组,并且是在JavaScript
中修改数组的首选方法。这种特殊的方法是测试索引与数组中的所有索引,并返回除传递的索引之外的所有索引。
现在,我们必须将该函数传递给组件,并在每个可以调用该函数的字符旁边绘制一个按钮。我们将removeCharacter
函数作为Table
的属性。
# src/App.js render() { const { characters } = this.state return ( <div className="container"> <Table characterData={characters} removeCharacter={this.removeCharacter} /> </div> ) } 复制代码
由于我们将其从Table
传递到TableBody
,因此我们将不得不像props
一样再次将其作为属性传递。
另外,由于事实证明,在我们的项目中仅由其自己的状态的组件是App
和Form
,因此最佳实际是将Table
从当前的类组件转换为简单的组件。
# src/Table.js const Table = (props) => { const { characterData, removeCharacter } = props; return ( <table> <TableHeader /> <TableBody characterData={characterData} removeCharacter={removeCharacter} /> </table> ); } 复制代码
这就是我们在removeCharacter()
方法中定义的索引的输入位置。在TableBody
组件中,我们将key/index
作为参数传递,因此过滤器函数知道要删除项目。我们将创建一个带有onClick
的按钮并将其传递。
# 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() 方法的函数,否则它将尝试自动运行。
太棒了,现在我们有了删除按钮,我们可以通过删除字符来修改状态。
我删除了Mac
数据。
现在,你应该了解如何初始化状态以及如何修改状态了。
提交表单数据
现在,我们已经将数据存储在状态中,并且可以从状态中删除任何项目。但是,如果我们希望能够添加新数据来到状态呢?在现实世界的应用程序中,你更有可能从空状态开始添加,例如代办事项列表或购物车。
开始前,我们从state.characters
中删除所有的硬编码的数据,因此我们现在将通过表单进行更新。
# src/App.js class App extends Component { state = { characters: [], } } 复制代码
现在,让我们继续在一个名为Form.js
的新文件中创建一个Form
组件。我们将创建一个类组件,并在其中使用一个constructor()
,到目前为止,我们还没做过。我们需要constructor()
来使用它,并接收父项的props
。
我们将把Form
的初始状态设置为具有一些空属性的对象,并将该初始状态分配给this.state
。
# src/Form.js import React, { Component } from 'react' class Form extends Component { constructor(props) { super(props) this.initialState = { name: '', job: '', } this.state = this.initialState } } 复制代码
我们对此表单的目标是,每次在表单中更改字段时都会更新Form
的状态,并且在我们提交时,所有这些数据将传递到App
状态,然后App
状态将更新Table
。
首先,我们将使该函数在每次对输入进行更改时都将运行。event
将传递,我们将设置Form
的状态为输入name
(键)和value
(值)。
# src/Form.js handleChange = event => { const { name, value } = event.target this.setState({ [name]: value, }) } 复制代码
在继续提交表单之前,我们需要这个运行起来。在渲染中,让我们从state
中获取两个属性,并将它们分配为正确的表单键对应的值。我们将把handleChange()
作为输入的onChange
运行,最后导出Form
组件。
# src/Form.js render() { const { name, job } = this.state; return ( <form> <label for="name">Name</label> <input type="text" name="name" id="name" value={name} onChange={this.handleChange} /> <label for="job">Job</label> <input type="text" name="job" id="job" value={job} onChange={this.handleChange} /> </form> ); } export default Form; 复制代码
在App.js
中,我们可以在下表中渲染表单。
# src/App.js return ( <div className="container"> <Table characterData={characters} removeCharacter={this.removeCharacter} /> <Form /> </div> ) 复制代码
现在,如果我们转到应用程序的前端,将会看到尚未提交的表单。更新一些字段,你将看到正在更新的Form
的本地状态。
太棒了。最后一步是允许我们实际提交该数据并更新父状态。我们将在App
上创建一个名为handleSubmit()
的函数,该函数通过使用ES6扩展运算符获取现有的this.state.characters
并添加新的character
参数来更新状态。
# src/App.js handleSubmit = character => { this.setState({ characters: [...this.state.characters, character] }) } 复制代码
确保我们将其作为Form
上的参数传递。
<Form handleSubmit={this.handleSubmit} /> 复制代码
现在,在Form
中,我们将创建一个称为SubmitForm()
的方法,该方法将调用该函数,并将Form
状态作为我们先前定义的character
参数传递。还将状态重置为初始化状态,以便在提交后清除表单。
# src/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
已经从状态中拉出,因此将正确显示。
如果你有疑问,你可以在我的github上查看源码。
拉取API数据
React
的一种非常常见的用法是从API
提取数据。如果你不熟悉什么是API
或者如何连接API
,我建议你阅读下如何使用JavaScript连接API这篇文章,它将引导你了解什么是API
以及如何将它们与原始的JavaScript
一起使用。
作为一个小测试,我们可以创建一个新的Api.js
文件,并在其中创建新的App
。我们可以测试的公共API
是Wikipedia API,我这里有一个URL断点,可以进行随机*
搜索。你可以点击刚才的连接进入查看API
- 当然,确保你的浏览器上安装了JSONView。
我们将使用JavaScript的内置Fetch从该URL
断点中收集数据并展示它。你只需要更改index.js
中的URL
-import App from './Api';
,即可在我们创建的应用程序与该测试文件之间切换。
我不会逐行解释此代码,因为我们已经学习了有关通过状态数组来创建组件,渲染和映射的知识。此代码的新方面是componentDidMount()
,这是一种React
生命周期方法。生命周期是在React
中调用方法的顺序。挂载mounting是指项目已经插入DOM
中。
当我们提取API
数据时,我们要使用componentDidMount
,因为我们要确保在导入数据之前已经将组件渲染到DOM
。在以下代码段中,你将看到我们如何从Wikipedia API
引入数据,并将其显示在页面上。
# Api.js 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 复制代码
一旦你在本地服务器中保存并运行此文件后,你将看到DOM
中显示的Wikipedia API
数据。
还有其他生命周期的方法,但是这里将不再讨论它们。你可以在此处于阅读有关React组件的更多信息。
*维基百科搜索选项可能不是随机的。 这可能是我在2005年率先发表的文章。
构建和发布一个React应用
到目前为止,我们所做的一切都在开发环境中。我们一直在进行即时的编译,热重载和更新。对于生产环境,我们将要加载静态文件 - 没有源代码。我们可以通过构建并部署它来做到这一点。
现在,如果你只想编译所有React
代码并将其放置在某个目录的根目录中,则只需运行以下代码:
npm run build 复制代码
这将build
一个包含你的应用程序的构建文件夹。将文件夹放在你想要的位置就可以了。
我们可以更进一步,让npm
为我们部署。我们将构建Github pages
,因此你必须熟悉Git并在Github
上获取代码。
确保你已经退出本地React
环境,因此该代码未在当前运行。首先,我们要在package.json
中添加一个homepage
字段,其中包含我们希望应用程序继续存在的URL
。
# package.json "homepage": "https://taniarascia.github.io/react-tutorial", 复制代码
我们也需要将下面的两行代码添加到scripts
的属性中。
# package.json "scripts": { // ... "predeploy": "npm run build", "deploy": "gh-pages -d build" } 复制代码
在你的项目中,将gh-pages
添加到devDependencies
npm install --save-dev gh-pages 复制代码
我们将创建build
,其中将包含所有已编译的静态文件。
npm run build 复制代码
最后,我们将部署到gh-pages
。
npm run deploy 复制代码
完成部署后,你可以通过https://taniarascia.github.io/react-tutorial 查看。
总结
本文很好地向你介绍了React
,简单组件和类组件,状态,属性,使用表单数据,从API
提取数据以及部署应用程序。使用React
还有更多的东西要学习和实践,但是我希望你现在有足够的信心钻研React
并学下去。