深入浅出React和Redux
上QQ阅读APP看书,第一时间看更新

1.2 增加一个新的React组件

React的首要思想是通过组件(Component)来开发应用。所谓组件,简单说,指的是能完成某个特定功能的独立的、可重用的代码。

基于组件的应用开发是广泛使用的软件开发模式,用分而治之的方法,把一个大的应用分解成若干小的组件,每个组件只关注于某个小范围的特定功能,但是把组件组合起来,就能够构成一个功能庞大的应用。如果分解功能的过程足够巧妙,那么每个组件可以在不同场景下重用,那样不光可以构建庞大的应用,还可以构建出灵活的应用。打个比方,每个组件是一块砖,而一个应用是一座楼,想要一次锻造就创建一座楼是不现实的。实际上,总是先锻造很多砖,通过排列组合这些砖,才能构建伟大的建筑。

React非常适合构建用户交互组件,让我们从创建一个React组件开始。

学习任何一门语言或者任何一门框架,往往是从写Hello World程序开始,不过只是展示一句Hello World并不足以体现React的神奇能力,所以,我们要做一个不那么简单的组件,为了体现React对交互功能的支持,我们做一个显示点击次数的组件。

我们先看一看create-react-app给我们自动产生的代码,在first-react-app目录下包含如下文件和目录:

src/
public/
README.md

package.json

node_modules/

在开发过程中,我们主要关注src目录中的内容,这个目录中是所有的源代码。

create-react-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的组件,App组件在同目录下的App. js文件中定义,渲染出来的效果就是在图1-1中看到的界面。

我们要定义一个新的能够计算点击数组件,名叫ClickCounter,所以我们修改index. js文件如下:

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

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

我们接下来会介绍代码的含义。现在我们先来看看如何添加一个新组件,在src目录下增加一个新的代码文件ClickCounter.js,代码如下:

import React, { Component } from 'react';
class ClickCounter extends Component {

  constructor(props) {
    super(props);
    this.onClickButton = this.onClickButton.bind(this);
    this.state = {count: 0};
  }

  onClickButton() {
    this.setState({count: this.state.count + 1});
  }

  render() {
    return (
      <div>
        <button onClick={this.onClickButton}>Click Me</button>
        <div>
        Click Count: {this.state.count}
        </div>
      </div>
    );
  }
}
export default ClickCounter;

图1-2 ClickCounter组件界面效果

如果你是从上一节不停顿直接读到这一节,而且没有关闭命令行中的npm start命令,当你保存完这个文件之后,不需要主动做刷新网页的动作,就会发现网页中的内容已经发生改变,如图1-2所示。

去点击那个“Click Me”按钮,可以看到“Click Count”后面的数字会随之增加,每点击一次加一。

恭喜你,现在你已经构建了一个有交互性的组件!

现在让我们来逐步详细解释代码中各部分的要义。

在index.js文件中,使用import导入了ClickCounter组件,代替了之前的App组件。

import ClickCounter from './ClickCounter';

import是ES6(EcmaScript 6)语法中导入文件模块的方式,ES6语法是一个大集合,大部分功能都被最新浏览器支持。不过这个import方法却不在广泛支持之列,这没有关系,ES6语法的JavaScript代码会被webpack和babel转译成所有浏览器都支持的ES5语法,而这一切都无需开发人员做配置,create-react-app已经替我们完成了这些工作。

在ClickCounter.js文件的第一行,我们从react库中引入了React和Component,如下所示:

import React, { Component } from 'react';

Component作为所有组件的基类,提供了很多组件共有的功能,下面这行代码,使用的是ES6语法来创建一个叫ClickCounter的组件类,ClickCounter的父类就是Component:

class ClickCounter extends Component {

在React出现之初,使用的是React.createClass方式来创造组件类,这种方法已经被废弃了,但是在互联网上依然存在大量的文章基于React.createClass来讲解React,这些文章中依然有很多真知灼见的部分,但是读者要意识到,使用React.createClass是一种过时的方法。在本书中,我们只使用ES6的语法来构建组件类。

细心的读者会发现,虽然我们导入的Component类在ClickCounter组件定义中使用了,可是导入的React却没有被使用,难道在这里引入React没有必要吗?

事实上,引入React非常必要,你可以尝试删掉第一行中的React,在网页中立刻会出现错误信息,如图1-3所示。

图1-3 缺失React的错误

这个错误信息的含义是:“在使用JSX的范围内必须要有React。”

也就是说,在使用JSX的代码文件中,即使代码中并没有直接使用React,也一定要导入这个React,这是因为JSX最终会被转译成依赖于React的表达式。

接下来,我们就要认识什么是JSX。