React组件的数据

React组件的数据

React 组件的数据分为两种, prop 和state ,无论 prop 或者 state 的改变,都可能引
发组件的重新渲染。prop 是组件的对外接口, state 是组件的内部状态,对外用
prop ,内部用 state。

React 的 prop

在React 中, prop ( property 的简写)是从外部传递给组件的数据, 一个 React 组件
通过定义自己能够接受的 prop 就定义了自己的对外公共接口。

每个 React 组件都是独立存在的模块,组件之外的一切都是外部世界,外部世界就
是通过 prop 来和组件对话的。

1. 给 prop 赋值

我们先从外部世界来看, prop 是如何使用的,在下面的 JSX 代码片段中,就使用了 prop:

1
2
3
4
<SampleButton
id="sample" borderWidth={2} onClick={onButtonClick}
style={{color :"red"}}
/>

在上面的例子中,创建了名为 SampleButton 的组件实例,使用了名字分别为 id、 borderWidth 、onClick 和style的 prop。当 prop 的类型不是字符串类型时,在 JSX 中必
须用花括号{}把 prop 值包住,所以 style 的值有两层花括号,外层花括号代表是 JSX
语法,内层的花括号代表这是一个对象常量。

2. 读取 prop 值

如果一个组件需要定义自己的构造函数,一定要记得在构造函数的第一行通过 super
调用父类也就是 React.Component 的构造函数 如果在构造函数中没有调用 super(props),
那么组件实例被构造之后,类实例的所有成员函数就无法通过 this.props 访问到父组件传
递过来的 props 值。很明显,给 this.props 赋值是 React. Component 构造函数的工作之一。

在构造函数的最后,我们可以看到读取传入 prop 的方法,在构造函数中可以通过参数
props 获得传入 prop 值,在其他函数中则可以通过 this.props 访问传入 prop 的值,比
如在 Counter 组件的 render 函数中,我们就是通过 this.props 获得传入的 caption。

React 的 state

驱动组件渲染过程的除了 prop ,还有 state, state 代表组件的内部状态。

1. 初始化 state

通常在组件类的构造函数结尾处初始化 state ,在 Counter 构造函数中,通过对 this.
state 的赋值完成了对组件 state 的初始化。

2. 读取和更新 state

在代码中,通过 this.state 可以读取到组件的当前 state。 值得注意的是,我们改变组件
state 必须要使用 this.setState 函数,而不能直接去修改 this.state。

this.setState ()函数所做的事情,首先是改变 this.state 的值,然后驱动组件
经历更新过程,这样才有机会让 this.state 里新的值出现在界面。

3. prop 和 state 的对比
  • prop 用于定义外部接口, state 用于记录内部状态;
  • prop 的赋值在外部世界使用组件时, state 的赋值在组件内部;
  • 组件不应该改变 prop 的值,而 state 存在的目的就是让组件来改变的。

组件的 state ,就相当于组件的记忆,其存在意义就是被修改,每一次通过 this.setState函数修改 state 就改变了组件的状态,然后通过渲染过程把这种变化体现出来。

组件的生命周期

React 严格定义了组件的生命周期,生命周期可能会经历如下三个过程:

  • 装载过程(Mount ),也就是把组件第一次在 DOM 树中渲染的过程;
  • 更新过程(Update ),当组件被重新渲染的过程;
  • 卸载过程(Unmount ),组件从 DOM 中删除的过程。

三种不同的过程, React 库会依次调用组件的一些成员函数,这些函数称为生命周期函数。

装载过程

当组件第一次被渲染的时候,依次调用的函数是如下这些:

  • constructor
  • getlnitialState
  • getDefaultProps
  • componentWillMount
  • render
  • componentDidMount
1. constructor

我们先来看第一个 constructor ,也就是 ES6 中每个类的构造函数,要创造一个组件
类的实例,当然会调用对应的构造函数。

要注意,并不是每个组件都需要定义自己的构造函数。在后面的章节我们可以看到,
无状态的 React 组件往往就不需要定义构造函数,一个 React 组件需要构造函数,往往是
为了下面的目的:

  • 初始化 state ,因为组件生命周期中任何函数都可能要访问 state ,那么整个生命
    周期中第一个被调用的构造函数自然是初始化 state 最理想的地方;
  • 绑定成员函数的 this 环境。

在ES6 语法下,类的每个成员函数在执行时的 this 并不是和类实例自动绑定的。而在构造函数中, this 就是当前组件实例,所以,为了方便将来的调用,往往在构造函数中
将这个实例的特定函数绑定 this 为当前实例。

以Counter 组件为例,我们的构造函数有这样如下的代码:

1
2
this.onClickIncrementButton = this.onClickIncrementButton.bind(this);
this.onClickDecrementButton = this.onClickDecrementButton.bind(this);

这两条语句的作用,就是通过 bind 方法让当前实例中 onClicklncrementButton和
onClickDecrementButton 函数被调用时, this 始终是指向当前组件实例。

2. getlnitialState 和 getDefaultProps

getlnitialState 这个函数的返回值会用来初始化组件的 this.state ,但是,这个方法只
有用 React. createClass 方法创造的组件类才会发生作用。

总之, getlnitialState和getDefaultProps 两个方法在 ES6 的方法定义的 React 组件中根本不会用到。

3. render

render函数是 React组件中最重要的函数,render 函数并不做实际的渲染动
作,它只是返回一个 JSX 描述的结构,最终由 React 来操作渲染过程。

在 render 函数中去调用 this.setState 毫无疑问是错误的,因为一个纯函数不应该引起状态的改变。

4. componentWillMount 和 componentDidMount

在装载过程中, componentWillMount 会在调用 render 函数之前被调用, componentDidMount
会在调用 render 函数之后被调用,这两个函数就像是 render 函数的前哨和后
卫,一前一后,把 render 函数夹住,正好分别做 render 前后必要的工作。

更新过程

当组件被装载到 DOM 树上之后,用户在网页上可以看到组件的第一印象,但是要
提供更好的交互体验,就要让该组件可以随着用户操作改变展现的内容,当 props 或者
state 被修改的时候,就会引发组件的更新过程。

更新过程会依次调用下面的生命周期函数,其中 render 函数和装载过程一样,没有差别。

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate
卸载过程

React 组件的卸载过程只涉及一个函数componentWillUnmount ,当React 组件要从
DOM 树上删除掉之前,对应的 componentWillUnmount 函数会被调用,所以这个函数适
合做一些清理性的工作。

------ 本文结束 ------
0%