淘先锋技术网

首页 1 2 3 4 5 6 7


   组件从创建到被销毁的过程称为 组件生命周期。React为组件在不同的生命周期阶段提供了不同的生命周期方法,让developer可以在组件的生命周期过程中更好地控制组件行为。组件生命周期被分为三个阶段: 挂载阶段更新阶段卸载阶段。React生命周期具体代码实现详见: React组件API参考文档。React16.8的新增特性Hook生命周期使用 Effect Hook,代码实现详见: 如何使用Effect Hook

一、挂载阶段(Mounting)

   这个阶段组件被创建,执行初始化,并被挂载到dom中,完成组件的第一次渲染。依次调用的生命周期方法有:

  • constructor
  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

1. constructor

   这是ES6 class的构造方法,组件被创建时,会首先调用组件的构造方法。当然,并不是每个组件都需要定义自己的构造函数,无状态的React组件往往就不需要定义构造函数,
执行时间:组件被加载前最先调用,并且只调用一次。
作用:

  • 继承父组件的Props
    super(props)
  • 初始化state
    组建生命周期中任何函数都可能要访问state,那么整个生命周期中第一个被调用的构造函数自然是初始化state最理想的地方;
    this.state={变量名:值}
  • 绑定成员函数的this环境
    this.函数名称 = this.函数名称.bind(this),目的在于,在render中调用时,可直接使用this.函数名称。
//首先这里继承了PureComponent 则意味着该组件使用了shouldComponentUpdate方法
class ListOfWords extends React.PureComponent {
  render() {
    return <div>{this.props.words.join(',')}</div>;
  }
}

class WordAdder extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      words: ['marklar']
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // This section is bad style and causes a bug
    const words = this.state.words;
    words.push('marklar');//数组的push方法返回的并不是一个新数组
    this.setState({words: words});
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick} />
        <ListOfWords words={this.state.words} />
      </div>
    );
  }
}

2. componentWillMount

   组件被挂载在DOM(render)之前调用,且只被调用一次。在这个方法中调用this.setState不会引起组件的重新渲染。

3. render

   React组件必不可少的核心组件,不能在该函数中修改状态state。

  • 执行时间:componentWillMount之后,componentDidMount之前,
  • 作用:渲染挂载组件
  • 触发条件:(1)初始化加载页面(2)状态机改变setState ( 3 ) 接收到新的props(父组件更新)

注:render函数并不做实际的渲染动作,组件在render中生成虚拟的DOM节点,即JSX,最后由React生成真实的DOM节点。

4.componentDidMount

   组件被挂载在DOM之后调用,且只被调用一次。这时候已经可以获取到DOM结构,因此依赖DOM节点的操作可以放到这个方法中,还可以用于像服务器请求数据。这个方法中调用this.setState会引起组件的重新渲染。

二、更新阶段(Updating)

   当组件被装载到DOM树之后,props或者state被修改可以引发组件更新。props引起的组件更新,本质上是由渲染该组件的父组件引起的,也就是当父组件的render方法被调用时,组件会发生更新过程,这个时候,组件props的值可能改变也可能没有发生改变,因为父组件可以使用相同的对象或值为组件props赋值。但无论props是否改变,父组件的render方法每一次调用,都会导致组件更新。state引起的组件更新,是通过调用this.setState修改组件state来触发的。组件更新阶段,依次调用的生命周期方法有:

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

1. componentWillReceiveProps(nextProps)

   这个方法只在props引起的组件更新过程中,才会被调用。state引起的组件更新并不会触发该方法执行。参数nextProps是父组件传递给当前组建新的props,它的值可能与子组件当前props值相等,往往需比较nextProps和this.props来决定是否执行props变化之后的逻辑。

2. shouldComponentUpdate(nextProps,nextState)

   这个方法决定组件是否继续执行更新过程。方法返回true(默认返回值),组件继续执行更新过程;返回false,组件更新过程停止,后续componentWillUpdate之类的方法也不会被调用。一般通过比较nextProps、nextState和组件当前props、state决定这个方法返回结果。这个方法可减少组件不必要渲染,从而优化组件性能。
上代码:

//该方法可以在继承Component类时自定义代码如下:
class CounterButton extends React.Component { //继承Component类
   constructor(props) {
     super(props);
     this.state = {count: 1};
   }
  //自定义shouldComponentUpdate方法
   shouldComponentUpdate(nextProps, nextState) {
     if (this.props.color !== nextProps.color) {
       return true;
     }
     if (this.state.count !== nextState.count) {
       return true;
      }
     return false;
  }

   render() {
      return (
        <button
           color={this.props.color}
           onClick={() => this.setState(state => ({count: state.count + 1}))}>
           Count: {this.state.count}
        </button>
     );
   }
}

3. componentWillUpdate(nextProps,nextState)

   此方法在组件render调用前执行,可以作为组件更新发生前执行某些工作的地方,一般很少用到。

4. render

   上面介绍过,这里不作多余赘述。

5. componentDidUpdate(prevProps,prevState)

   组件更新后被调用,可以操作更新后的DOM。两个参数代表组件更新前的props和state.

三、卸载阶段(Unmounting)

   组件从DOM中被卸载的过程,只有一个生命周期方法:

  • componentWillUnmount

componentWillUnmount

   这个方法在组件被卸载之前调用,可以在这里执行一些清理工作是,比如清除组件中使用的定时器,清除componentDidMount中手动创建的DOM元素等,以避免内存泄漏。

注:只有类组件才具有生命周期的方法,函数组件没有生命周期的方法,因此永远不要在函数组件中使用生命周期方法。

番外篇:此为作者第一篇博客,博客内容主要是在项目过程中总结的学习笔记和踩过的坑,供大家借鉴学习。还有一点,平时一定要注意思考和总结,重要的事情说三遍,思考总结!思考总结!思考总结!