React入门教程 – 概述和实际演练

10年服务1亿Tian开发工程师

本文概述和实际演练 React 的基本概念,例如组件,state(状态) 和 props(属性),以及提交表单,从 API 获取数据以及将 React 应用程序部署到生产环境。

自从我第一次开始学习 JavaScript 以来,我一直都有听说 React ,但我承认我只粗略的看了一下 React 相关内容就被吓到了。我看到一堆 HTML 和 JavaScript 混合在一起的代码,我想,这不是我们一直试图避免的吗? React 有什么大不了的?

相反,我只专注于学习原生的 JavaScript 并在专业环境中使用 jQuery 。在经历了几次失败的尝试之后,我终于开始尝试使用 React ,我开始明白了为什么我要使用 React 而不是原生的 JS 或 jQuery

我试着将我学到的所有内容浓缩成这篇很好的介绍文章,并与你分享。

预备知识

在开始使用 React 之前,您应该事先知道一些事情。 例如,如果您以前从未使用过 JavaScript 或 DOM ,那么在尝试使用 React 问题之前,你应该首先熟悉它们。

以下是我认为是React的先决条件。

  • 基本熟悉 HTML 和 CSS
  • JavaScript 基础知识和本赛季思想。
  • 对 DOM 有基本的了解。
  • 熟悉 ES6 语法和功能
  • Node.js 和 npm 全局安装。

目标

  • 了解必要的 React 概念和相关术语,例如 Babel,Webpack,JSX,components(组件),props(属性),state(状态) 和 生命周期。
  • 构建一个非常简单的 React 应用程序,实际演练上述概念。

本文 已经放到了GitHub上。

什么是 React ?

  • React 是一个 JavaScript 库 – 最受欢迎的库之一,在 。
  • React 不是一个框架(与 Angular 不同,后者更 opinionated (倾向性))。
  • React 是一个由 Facebook 创建的开源项目。
  • React 用于在Tian构建用户界面(UI)。
  • React 是 MVC(Model View Controller,模型视图控制) 应用程序的 视图 层。

React 最重要的一个方面是,您可以创建 components(组件),类似于自定义,可重用的HTML元素,可以快速高效地构建用户界面。 React 还利用 state(状态) 和 props(属性) 简化了数据的存储和处理方式。

我们将在整篇文章中详细介绍所有这些内容,让我们开始吧。

设置和安装

设置 React 有几种方法,我会在这里告诉你种方法,这样你就可以很好地了解它是如何工作的。

静态HTML文件

第一种方法不是设置 React 的流行方式,本教程的其余部分也不是使用这个方法的,但是如果你曾经使用像 jQuery 这样的库,那么这种你将会很熟悉且易于理解,如果你不熟悉 Webpack ,Babel 和 Node.js ,那么可以使用这种最简单的方法开始。

让我们从制作一个基本的 index.html 文件开始。 我们将在头部加载三个 CDN 文件- React,React DOM 和 Babel 。 我们还将创建一个 id 为 rootdiv 元素,最后我们将创建一个 script 标签,您的自定义代码将都放在这里。

<!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/[email protected]/babel.js"></script>
</head>

<body>

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

    <script type="text/babel">
        // React 代码将放在这里
    </script>

</body>

</html>

在撰写本文时,我加载的是最新的稳定版本的 React 。

  • React – React 顶级 API, 。
  • React DOM – 添加特定于 DOM 的方法 。
  • – 一种 JavaScript 编译器,允许我们在旧浏览器中使用 ES6+

我们的应用程序的入口点将是 id 为 rootdiv 元素,它按惯例命名。 您还会注意到 text/babel 脚本类型,这对于使用 Babel 是必需的。

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

class App extends React.Component {
   //...
}

现在我们将添加 render() 方法,这是类组件中唯一必须的方法,用于渲染 DOM 节点。

class App extends React.Component {
    render() { 
        return (
           //...
        ); 
    } 
}

return 内部 ,看起来像一个简单的 HTML 元素。请注意,我们不需要在此处返回 String 类型的字符串,因此请不要使用引号将元素括起来。这里的内容被称为 JSX ,我们很快将在下面的文章中了解它。 (注:这里是 ,有兴趣你可以先了解一下。)

class App extends React.Component {
    render() { 
        return (
           <h1>Hello React!</h1>
        ); 
    } 
}

最后,我们将使用 React DOM 的 render() 方法将我们创建的 App 类渲染到 HTML 中的 id 为 rootdiv 元素中。

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

这是 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/[email protected]/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 ,您将看到我们创建的 h1 标签已经渲染到 DOM 中。

我们创建的 <code/>h1 标签已经渲染到 DOM 中” /></p>
<p>酷!既然你已经完成了这个,你可以看到开始使用 React 并不是那么糟糕是不是? 它只是一些我们可以加载到 HTML 中的 JavaScript 帮助程序库。</p>
<p>我们这样做是出于演示的目的,但从现在开始我们将使用另一种方法:Create React App 。</p>
<h3>Create React App</h3>
<p>我刚刚将 React 库和 Babel 加载到静态 HTML 页面中,并动态渲染,但是我们发现那种方法效率不高,而且难以维护。</p>
<p>幸运的是,Facebook 创建了  ,这是一个 React 开发环境,预先配置了构建 React 应用程序所需的一切。 它将创建一个实时开发服务器,使用 Webpack 自动编译 React,JSX 和 ES6,自动加载 CSS 文件,并使用 ESLint 测试和警告代码中的错误。</p>
<p>要设置 <code>create-react-app</code> ,请在项目所在目录的终端中运行以下代码。 请确保 Node.js 5.2或更高版本。</p>
<pre class= npx create-react-app react-tutorial

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

cd react-tutorial
npm start

此命令运行后,浏览器将在一个新窗口中打开新的 React 应用程序,网址为: localhost:3000

用 Create React App 创建 React 应用

如果查看项目结构,您将看到 /public/src 目录,以及常规的 node_modules.gitignoreREADME.mdpackage.json

/public 中,重要文件是 index.html,它与我们之前制作的静态 index.html 文件非常相似 – 只是一个 root div。 在这里,index.html 文件中没有加载任何库或脚本。/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,我只是将 的内容复制并粘贴到文件中。 如果需要,可以使用 Bootstrap 或任何您想要的 CSS 框架,或者根本不使用。 我发现它更容易使用。

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

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

让我们再次创建我们的 App 组件。 之前,我们只有一个 <h1> 标签,但现在我在一个div元素中加入了一个样式类。 您会注意到我们使用 className 而不是 class。 这是我们第一次暗示这里编写的代码是JavaScript,而不是 HTML 。

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

最后,我们将像以前一样将应用程序渲染到 root div 中。

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

这是我们的完整 index.js 。这次,我们将 Component 作为 React 的 property(属性) 加载,因此我们不再需要扩展 React.Component

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 开发人员工具

React Developer Tools 扩展可以让您在使用 React 时更轻松。 下载 或您喜欢的任何浏览器。

安装后,当您打开开发人员工具时,您将看到 React 的选项卡。 单击它,您将能够在编写组件时对其进行检查。 您仍然可以转到 Elements 选项卡以查看实际的 DOM 输出。 现在看起来似乎不太合适,但随着应用程序变得越来越复杂,使用它将变得越来越必要。

React Developer Tools 扩展

现在我们拥有了实际开始使用 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类,因为 class 是 JavaScript 中的保留关键字。
  • JSX 中的属性和方法是 camelCase(驼峰命名) – onclick 将写成 onClick
  • 自动闭合标签必须以斜线结尾 – 例如 <img />

JavaScript表达式也可以使用花括号嵌入到 JSX 中,包括变量,函数和属性。

const name = 'Tania';
const heading = <h1>Hello, {name}</h1> ;

JSX 比在原生的 JavaScript 中创建和附加多个元素更容易编写和理解,这也是人们喜欢React的原因之一。

更多信息请查看 React 中文文档中的 和

组件(Components)

到目前为止,我们已经创建了一个组件– App 组件。 React 中的几乎所有内容都由组件组成,组件可以是 class components(类组件)或 simple components(简单组件,注普遍的叫法为 functional components ,也就是函数式组件)。

大多数 React 应用程序都有许多小组件,所有内容都加载到主 App 组件中。 组件也经常有自己的文件,所以来修改一下我们的项目试试。

index.js 中删除 App 类,所以它看起来像这样。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';

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

我们将在 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;

我们将组件 export(导出) 为 App 并将其加载到 index.js 中。将组件分离到单独文件中并不是强制的,但如果不这样做,应用程序将开始变得笨拙,达到一定程度将难以维护,甚至失控。

类组件(Class Components)

让我们来创建另一个组件。 我们要创建一个表格,命名为 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;

我们创建的这个组件是一个自定义 class components(类组件)。 我们将自定义组件的首字母大写,以区别于常规 HTML 元素。 回到 App.js ,我们可以用 Table 名称来加载她,首先 import(导入) 它:

import Table from './Table';

然后将它加载到 Apprender() 方法中,也就是把之前的 “Hello, React!” 替换掉。我还修改了外容器的样式类 container

return (
    <div className="container">
        <Table />
    </div>
);

如果您重新在浏览器中查看,则会看到 Table 已经被加载进来了。

Table组件已经被加载进来了

现在我们已经看到了自定义类组件是什么。我们可以一遍又一遍地重用这个组件。但是,由于数据是硬编码的,因此目前不太好用。

函数式组件(Functional Components)

注:原文中的叫法是 简单组件(Simple Components),翻译的时候用了官方的叫法 functional components ,也就是函数式组件。可以查看官方文档《》 中关于 函数式组件和类组件 的描述。

React 中的另一种组件是 functional components(函数式组件),它是一个函数。这种组件不使用 class 关键字。 让我们为 Table 组件制作两个函数式组件 – table header(表头) 和 table body(表体) 。

我们将使用 ES6 箭头函数来创建这些简单组件。 首先是表头:

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>
        );
    }
}

一切都应该像以前一样出现。如您所见,组件可以嵌套在其他组件中,并且可以混合函数式组件和类组件。

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

我们来比较一下 functional components(函数式组件)和 class components(类组件)。

functional components(函数式组件):

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

class components(类组件)

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

请注意,如果 return 内容包含在一行中,则不需要用花括号括起来了。

了解关于组件的更多信息请查看官方文档《》(中文)。

Props(属性)

现在,我们有了一个很好的 Table 组件,但数据是硬编码的。 React 最重要的特性之一就是处理数据的方式,它使用 props(属性) 和 state(状态) 来实现。首先,我们将重点讨论如何使用属性(props)来处理数据。

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

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

然后让我们将所有数据移动到一个由对象组成的数组中,就好像我们引入了一个基于 JSON 的 API 一样。我们必须在 render() 中创建这个数组。

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 表达式。

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

现在我们将数据传递给了 Table,我们必须在Table组件中访问它。

class Table extends Component {
    render() {
        const { characterData } = this.props;

        return (
            <table>
                <TableHeader />
                <TableBody characterData={characterData} />
            </table>
        );
    }
}

如果打开 React DevTools 并检查 Table 组件,您将在属性中看到数据数组。这里存储的数据称为 virtual DOM(虚拟DOM) ,这是一种快速有效的方法,可以将数据与实际 DOM 同步。

virtual DOM(虚拟DOM)

但是,这些数据还没有被渲染到实际的 DOM 中。 在 Table 中,我们可以通过 this.props 访问所有 props(属性)。 我们通过 characterData 只传递了一个 props(属性),所以我们将使用 this.props.characterData 来读取该数据。

我将使用 ES6 属性简写的方式来创建包含 this.props.characterData 的变量。

const { characterData } = this.props;

由于我们的 Table 组件实际上由两个较小的函数式组件组成,因此我将再次通过 props(属性) 将数据传递给 TableBody

class Table extends Component {
    render() {
        const { characterData } = this.props;

        return (
            <table>
                <TableHeader />
                <TableBody characterData={characterData} />
            </table>
        );
    }
}

现在,TableBody 不带参数并返回一个单独的标签。

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

我们将把 props(属性) 作为参数传递,并通过 以返回数组中每个对象的 table row (表行)。这个映射将包含在 row 变量中,我们将以表达式的形式返回这个变量。

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>;
}

如果你在浏览器中查看应用程序,则现在已经加载了所有数据。

您会注意到我已经为每个 table row(表行) 添加了一个键索引。 在 React 中创建列表时应始终使用 ,因为它们有助于识别每个列表项。 当我们想要操作列表项时,我们还将看到这一点有多么的重要。

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

查看官方文档《》(中文) 和 《》以了解更多本章节中介绍的内容。

State(状态)

现在,我们将 character 数据以数组的形式存储在变量中,并将其作为 props(属性) 传递。 这是很好的开始,但想象一下,我们是否希望能够从数组中删除一项元素。 使用 props(属性) ,我们有单向数据流,但有了 state(状态),我们可以更新组件中的私有数据。

您可以将 state(状态) 视为任何应该保存和修改的数据,而不必添加到数据库中,例如,在确认购买之前从购物车中添加和删除商品。

首先,我们将创建一个 state(状态) 对象。

class App extends Component {
    state = {};

该对象将包含您要在 state(状态) 中存储的所有内容的属性。对于这个例子来说,是 characters

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

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

class App extends Component {
    state = {
        characters: [
            {
                'name': 'Charlie',
                // the rest of the data
        ]        
    };

我们的数据正式包含在 state(状态) 中了。 由于我们希望能够从表中删除一个人物(一条记录),因此我们将在父 App 类上创建一个 removeCharacter 方法。

要检索 state(状态) ,我们将使用与以前相同的 ES6 方法获取 this.state.characters 。 要更新 state(状态) ,我们将使用 this.setState(),这是操作 state(状态) 的内置方法。 我们将根据我们传递的索引 ,并返回新数组。

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

removeCharacter = index => {
    const { characters } = this.state;

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

filter 不会改变原来的数组,而是创建一个新数组,并且是在 JavaScript 中修改数组的首选方法。 这个特殊的方法是测试索引与数组中的所有索引,并返回除了传递的索引之外的所有索引元素。

现在我们必须将该函数传递给组件,并在每个可以调用该函数的人物项旁边呈现一个按钮。 我们将 removeCharacter 函数作为 prop(属性) 传递给 Table

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

由于我们将它从 Table 传递给 TableBody ,我们将不得不再次将其作为 prop(属性) 传递,就像我们对 character(人物) 数据所做的那样。

class Table extends Component {
    render() {
        const { characterData, removeCharacter } = this.props;

        return (
            <table>
                <TableHeader />
                <TableBody 
                    characterData={characterData} 
                    removeCharacter={removeCharacter} 
                />
            </table>
        );
    }
}

这是我们在 removeCharacter() 方法中定义的索引的位置。在 TableBody 组件中,我们将 key/index(键/索引) 作为参数传递,因此 filter 函数知道要删除的是哪一项。 我们将创建一个带有 onClick 的按钮并将其传递给它。

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

onClick 函数必须通过一个返回 removeCharacter() 方法的函数,否则它将尝试自动运行。

真棒。现在我们已经有了删除按钮,我们可以通过删除一个 character(人物) 来修改我们的 state(状态) 。

删除按钮

我删除了 Mac 。

现在您应该了解 state(状态) 是如何初始化的,以及如何修改 state(状态) 。

提交表格数据

现在我们将数据存储在 state(状态) 中,我们可以从 state(状态) 中删除任何数据项。 但是,如果我们希望能够向 state(状态) 添加新数据呢? 在现实的应用程序中,您更可能从空 state(状态) 开始,并将数据添加到 state(状态) 中,例如使用待办事项列表( to-do list) 或购物车。

在接下来我们要做的任何事情之前,让我们从 state.characters 中删除所有硬编码数据,因为我们接下来将通过表单更新 state(状态) 中的数据。

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

现在让我们继续,我们首先创建一个名为 Form.js 的新文件,在其中创建一个 Form 组件。 我们将创建一个类组件,并且我们将使用constructor(),这是我们到目前为止尚未接触到的。 我们需要 constructor() 来使用它,并接收父级的 props(属性) 。

我们将把 Form 的初始 state(状态) 设置为具有一些空属性的对象,并将该初始 state(状态) 分配给 this.state

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 将被传递,我们将 Form 的 state(状态) 设置为输入的 name(键)和 value

handleChange = event => {
    const {name, value} = event.target;

    this.setState({
        [name] : value
    });
}

在我们继续提交表单之前,让我们先完成这个工作。在 render() 方法中,让我们从 state(状态) 中获取两个属性,并将它们指定为对应于适当形式键的值。我们将运行 handleChange() 方法作为 input 的 onChange ,最后 export(导出) 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 中,我们可以在表格下方渲染表单。

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

现在,如果我们回到浏览器,我们会看到一个尚未提交的表单。更新一些字段,您将看到 Form 的本地 state(状态) 正在更新。

Form 的本地 state(状态) 正在更新

最后一步是允许我们实际提交该数据并更新父状态。 我们将在 App 上创建一个名为 handleSubmit() 的函数,该函数将使用现有的this.state.characters 并使用 添加新的 character 参数来更新 state(状态) 。

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

让我们确保我们把它作为一个参数传递给 Form

<Form handleSubmit={this.handleSubmit} />

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

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

最后,我们将添加一个提交按钮来提交表单。我们使用 onClick 而不是 onSubmit ,因为我们没有使用标准提交(submit)功能。点击将调用我们刚刚创建的 submitForm 方法。

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

就是这样! 该应用程序已完成。 我们可以在表格中创建,添加和删除用户。 由于 TableTableBody 已经从 state(状态) 获取数据,它将正确显示。

应用程序已完成

更多关于 state(状态) 的信息请阅读 React 中文文档中的《》

如果您在学习过程中有点迷茫或者混乱,可以在 。

引入API数据

React 应用开发过程中一个非常常见的用法是从 API 中获取数据。如果您不熟悉 API 是什么或者如何连接到 API ,我建议您阅读,它将引导您了解 API 以及如何将它们与原生的 JavaScript 一起使用。

作为一个小测试,我们可以创建一个 Api.js 文件,并在那里创建一个新的App。我们可以测试的公共 API 是 ,我在这里有一个 用于 random(随机)*搜索。您可以转到该链接查看 API ,并确保在浏览器上安装了 。

我们将使用 从该 URL 终端收集数据并显示它。您可以通过更改 index.js 中的URL,来切换我们创建的应用程序和此测试文件 – import App from './Api';

我不会逐行解释这个代码,因为我们已经学会了创建组件,渲染和映射 state(状态) 数组。此代码的新方面是 componentDidMount(),一个 React 生命周期方法。Lifecycle(生命周期) 是 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;

在本地服务器中保存并运行此文件后,您将看到 DOM 中显示了来自 Wikipedia API 的数据。

React 从 API 中获取数据

还有其他生命周期方法,但重复这些方法将超出本文的范围。您可以在 React 中文文档中阅读《》,以及。

构建和部署 React 应用程序

到目前为止,我们所做的一切都处于开发环境中。 我们一直在编译,热重新加载和更新。 对于生产环境,我们将要加载静态文件 – 没有源代码。 我们可以通过构建和部署它来实现这一目标。

现在,如果您只想编译所有 React 代码并将其放在某个目录的根目录中,那么您需要做的就是运行以下行:

npm run build

这将为你创建一个应用程序的 build 文件夹。 将该文件夹的内容放到任何地方,就没你什么事情了,轻松搞定!

我们还可以更进一步,让 npm 为我们部署。我们将构建到 GitHub 页面,因此您必须 并在GitHub上安装代码。

确保您已退出本地 React 环境,因此代码当前未运行。 首先,我们将向 package.json 添加一个homepage字段,该字段包含我们希望我们的应用程序存在的URL。

"homepage": "https://taniarascia.github.io/react-tutorial",

我们还将这两行添加到 scripts 属性中。

"scripts": {
  // ...
  "predeploy": "npm run build",
  "deploy": "gh-pages -d build"
}

在您的项目中,您将向devDependencies添加 gh-pages

npm install --save-dev gh-pages

我们将创建 build ,它将包含所有已编译的静态文件。

npm run build

最后,我们将部署到 gh-pages

npm run deploy

到这里我们的教程就结束了!该应用程序现已在 上发布。

总结

本文为你介绍 React 的基本概念,包括函数式和类组件、state(状态)、props(属性)、处理表单数据,从一个 API 中获取,构建及部署一个应用程序。 React还有很多东西要学习和做,但我希望你现在能够自信地钻研 React。

  • 项目源代码:
  • 示例浏览:

如果有任何不清楚的地方,或者您希望在本文或后续文章中看到其他任何内容,欢迎留言告知我们。

推荐资源及文章

英文原文:

赞(6) 打赏
未经允许不得转载:WEBTian开发 » React入门教程 – 概述和实际演练

评论 2

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #-49

    state状态:在组件App添加state对象,把之前render里面的数组移到里面, 那render里面的数组不保留的话? 下面return报错:characters未找到? 这里没看明白
    class App extends Component {
    state = {
    characters: []
    };

    v_hfang2个月前 (11-13)回复
  2. #-48

    上述问题忽略,找到问题了,在render方法return里面需求这样写: characterData={this.state.characters}

    v_hfang2个月前 (11-13)回复

Tian开发相关广告投放 更专业 更精准

联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏