阅读 906

【译】开始学习React - 概览和演示教程

当我刚开始学习JavaScript的时候,我就听说了React,但我承认看了它一眼,它吓到我了。我看到了看起来一堆HTMLCSS的混合思想,这不是我们一直努力避免的事情吗?React有什么了不起的?

相反,我只专注于学习原始的JavaScript,并在需要的时候使用jQuery。经过几次失败的React入门尝试之后,我终于开始了解它了,我开始明白为什么我可能想使用React而不是原始的JSjQuery

我试图将自己学到的内容浓缩成一个很好的介绍,以便与你分享,下面就是~

预备知识

在开始学习React之前,你应该事先了解一些事情。例如,如果你之前从没接触过JavaScript或者DOM,那么在解决React之前,你要更加熟悉它们。

下面是我认为学习React的预备知识:

目标

  • 了解基本的React概念和相关术语,例如BabelWebpackJSX,组件,属性,状态和生命周期
  • 通过构建一个非常简单的React应用程序,以演示上面的概念。

下面是最终的相关源代码和示例。

React是什么?

  • React是一个JavaScript库 - 最受欢迎的库之一,在GitHub上超过100,000星星
  • React不是一个框架(不像Angular,定位是框架)。
  • ReactFacebook的开源项目。
  • React用于在前端构建用户界面UI
  • ReactMVC (Model View Controller)应用的View层。

React的最重要的方面之一是可以创建类似于自定义、可复用的HTML元素的组件,以快速有效地构建用户界面。React还使用状态state属性props来简化数据的存储和处理方式。

我们将在本文中介绍这些内容及其更多的内容,我们来开始吧。

安装

有几种安装React的方法,我将向你展示两种,以便你更好地了解它地工作方式。

静态HTML文件

第一种方法不是安装React的流行方法,也不是我们本教程其余部分的工作方式,但是如果你接触过jQuery之类的库,这将很熟悉并易于理解。如果你不熟悉WebpackBabelNode.js,那这将是种恐怖的入门方式。

让我们开始创建一个基本的index.html文件。我们将在头部head中加载三个CDN资源 - ReactDOMBabel。我们还将创建一个idrootdiv,最后,我们将创建一个脚本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>
复制代码

在编写本文的时,我加载的库是稳定版本的。

  • React - React顶级API
  • React DOM - 添加特定于DOM的方法
  • Babel - JavaScript编辑器,使我们可以在旧的浏览器中使用ES6+

我们应用程序的入口点是root div元素,该元素按惯例命名。你还会注意到text / babel的脚本类型,这是使用Babel所必需的。

现在,让我们编写React的第一个模块代码。我们将使用ES6类来创建一个名为AppReact组件。

# 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 DOMrender()方法将我们创建的App类渲染到HTMLroot容器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,将看到我们创建的呈现给DOMh1标签。

hello world

太棒了!现在你完成了这一步,你可以看到React并没有那么让人着迷。只是一些JavaScript帮助教程库,我们将其加载到HTML中。

我们出于演示目的完成了此操作,但是从这里开始,我们将使用另一种方式:Create React App

创建React App

我刚刚使用的是将JavaScript库加载到静态HTML页面中并动态渲染ReactBabel的方法不是很有效,并很难维护。

幸运的是,Facebook创建了Create React App,该环境预先配置了构建React所需要的一切。它将创建一个实时开发服务器,使用webpack自动编译ReactJSXES6,自动为CSS文件加前缀,并使用ESLint测试和警告代码中的错误。

要设置create-react-app,你要在终端运行以下代码,该代码位于你希望项目所在的目录。请确保你安装了5.2以上版本的Node.js

npx create-react-app react-tutorial
复制代码

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

cd react-tutorial
npm start
复制代码

运行此命令之后,新的React应用程序将在浏览器的localhost:3000弹出一个新窗口。

welcome to react

如果你查看项目结构,将会看到/public/src目录,以及常规的node_modules.gitignoreREADME.mdpackage.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.cssindex.js

对于index.css,我只是将原始Primitive CSS 的内容复制并粘贴到文件中。如果需要,可以使用Bootstrap或所需的任何CSS框架,或者什么都不用。我只是觉得更容易使用而已。

index.js中,我引入了ReactReactDOMCSS文件。

# 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 devtools

现在,我们拥有了实际开始使用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'
复制代码

然后通过将其加载到Apprender()中,然后获得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已加载。

class component

现在,我们了解了什么是自定义类组件。我们可以反复使用此组件。但是,由于将数据硬编程(即写死)在其中,因此目前它并不太实用。

简单组件

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文件如下所示。请注意,TableHeaderTableBody组件都在同一个文件中,并且由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 />
}
复制代码

然后,将所有数据移到对象数组中,就像我们引入基于JSONAPI一样。我们必须在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同步快速有效的方法。

inspect props

但是,此数据尚未在实际的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一样再次将其作为属性传递。

另外,由于事实证明,在我们的项目中仅由其自己的状态的组件是AppForm,因此最佳实际是将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() 方法的函数,否则它将尝试自动运行。

太棒了,现在我们有了删除按钮,我们可以通过删除字符来修改状态。

state demo

我删除了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的本地状态。

form state

太棒了。最后一步是允许我们实际提交该数据并更新父状态。我们将在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} />
复制代码

就是这样!该应用程序已经完成了。我们可以在表中创建,添加和删除用户。由于TableTableBody已经从状态中拉出,因此将正确显示。

add_state

如果你有疑问,你可以在我的github上查看源码。

拉取API数据

React的一种非常常见的用法是从API提取数据。如果你不熟悉什么是API或者如何连接API,我建议你阅读下如何使用JavaScript连接API这篇文章,它将引导你了解什么是API以及如何将它们与原始的JavaScript一起使用。

作为一个小测试,我们可以创建一个新的Api.js文件,并在其中创建新的App。我们可以测试的公共APIWikipedia 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数据。

api data

还有其他生命周期的方法,但是这里将不再讨论它们。你可以在此处于阅读有关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并学下去。

参考&后话

关注下面的标签,发现更多相似文章
评论