react的生命周期函数

来源:互联网 发布:怎么看链接是淘宝客 编辑:程序博客网 时间:2024/05/22 08:01

React组件的生命周期及执行顺序

461人阅读 评论(0)收藏举报
分类:

目录(?)[+]

本文原创地址链接:http://blog.csdn.net/zhou_xiao_cheng/article/details/52461414,未经博主允许不得转载。
觉得学习React,了解它的生命周期是很重要的。这次,让我们一起来看看,到底什么是组件的生命周期?
按照我的理解,组件生命周期一般指的是:组件从被创建到它消亡的过程,因此,组件生命周期方法就是指:在这个过程(创建 ->消亡)中,在一个特定的点会被调用的方法。
简单点说,我们可以把组件的生命周期看作是一根平铺于桌面的线,这根线上系了很多钩子,钩子都钩着一个方法,当从线的一头提起这根线,那么钩子(连同它们上面的方法)都会被逐一提起,这个过程,就是React组件生命周期方法被逐一调用的过程了,至于调用的顺序,接下来会讲到。
俗话说得好,凡事都有例外,如果你只是单纯地想用一个无状态的JavaScript函数(没有state)来定义一个React组件,如下:

function StatelessFunc(props) {  return <div>{props.name}</div>;}ReactDOM.render(<StatelessFunc name="zhou xiao cheng" />, document.getElementById('app'));
  • 1
  • 2
  • 3
  • 4

那么,这个组件就是没有生命周期的,因为它只是在简单地做函数输出。但你可以在该组件上设置你的defaultProps(例如:StatelessFunc.defaultProps = { name: 'zhou' })及propTypes,官方建议我们多使用这样的无状态函数来作为组件,以便将来可能会用避免不必要的检查和内存分配的方式来对这些组件进行优化。

生命周期方法介绍

对于一个包含着生命周期的组件,有以下可选的生命周期方法:

  1. componentWillMount()
    仅在render()方法前被调用一次,如果在该方法中调用了setState方法去改变组件的状态值,那么调用render()后,将会直接看到改变过了的状态值,并且不论状态值怎么改变,componentWillMount()都不会再被调用。

    class Demo extends React.Component {  constructor() {    super()    this.state = {      value: 0    }  }  componentWillMount() {    this.setState({      value: this.state.value + 1    })    console.log('123')  }  render() {    return (      <div>{this.state.value}</div>    )  }}ReactDOM.render(<Demo />, document.getElementById('app'))ReactDOM.render(<Demo />, document.getElementById('app'))
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  2. componentDidMount()
    仅在render()方法后被立即调用一次(客户端),相对于父组件而言,该方法在子组件中会先被调用。如果需要使用一些JaveScript框架或者类似于setInterval()这样的方法,建议在该方法内使用。

  3. ShouldComponentUpdate(object nextProps, object nextState)
    在初始渲染调用render()方法时不会被调用,后面在接受到新的state或者props时,在render()方法前被调用。为防止一些潜在的bug,该方法默认总是返回true。如果你确定state及props改变后不需要渲染组件,那么也可以指定返回false,需要注意的是,这样的结果会导致后面的render()、componentWillUpdate()、componentDidUpdate()都不会被调用。

  4. componentWillReceiveProps(object nextProps)
    在初始渲染调用render()方法时不会被调用,当接收到一个新的props时,该方法被调用。我们都知道,如果改变一个状态的值,则会触发render()方法,所以可以在这个方法里调用setState()方法去改变一个状态的值,当该方法接收到新的props时,setState()就可以避免一次额外的render()了。
    在这个方法里,尤其需要注意一点,就是接收到新的props一定会触发render()方法,但是render()方法被触发不一定是因为接收到了新的props(具体请戳这里)。如下:

    class Demo extends React.Component {  componentWillReceiveProps(nextProps) {    console.log('componentWillReceiveProps is invoked', nextProps.val.name)  }  render() {    return (      <div>{this.state.value}</div>    )  }}var data = {  name: 'zhou xiao cheng'}ReactDOM.render(<Demo val={data} />, document.getElementById('app'))ReactDOM.render(<Demo val={data} />, document.getElementById('app'))ReactDOM.render(<Demo val={data} />, document.getElementById('app'))
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在上面的代码中,props没有发生改变,但render()方法却被调用了两次。

  5. componentWillUpdate(object nextProps, object nextState)
    在初始渲染调用render()方法时不会被调用,当接收到新的props及state时,在render()方法之前被调用。

  6. componentDidUpdate(object prevProps, object prevState)
    在初始渲染调用render()方法时不会被调用,当组件更新被刷新到DOM之后被立即调用。

  7. componentWillUnmount()
    在组件从DOM上卸载前被调用,在这个方法里面,我们主要是完成一些清除操作,比如说清除掉一些过时了的定时器等。

组件规范介绍

除了上面的7个可选的生命周期方法,我们可以将剩下的一些方法称之为组件规范。接下来,我们将会对一些较为常用的组件规范进行介绍。

  1. render()
    对于一个组件而言,render()方法是必须的,通常,在这个方法里面,我们都会返回一个元素(如:<div></div>),但同样也可以返回falsenull,这意味着我们没有任何东西需要渲染。

  2. getInitialState()
    在ES6的语法中,这个方法可以写成下面这样(将其写在构造函数中,this.state的值就是状态初始值),其效果是一样的:

    class Demo extends React.Component {  constructor() {    super()    this.state = {      key: value    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  3. getDefaultProps()
    ES6的语法中,写法如下:

    Demo.defaultProps = {key: value}
    • 1

    ES7中,还可以写成这样(但需要配合Babel转换器进行使用):

    class Demo extends React.Component {  static defaultProps = {    key: value  }}
    • 1
    • 2
    • 3
    • 4
    • 5
  4. propTypes
    ES6的语法中,写法如下(想了解更多propTypes请戳官方propTypes介绍):

    Demo.propTypes = {  requiredFunc: React.PropTypes.func.isRequired}
    • 1
    • 2
    • 3

    同样,在ES7中,可以写成下面这样:

    class Demo extends React.Component {  static propTypes = {    requiredFunc: React.PropTypes.func.isRequired  }}
    • 1
    • 2
    • 3
    • 4
    • 5
  5. static
    ES6语法中,static关键字则允许我们定义一个在组件类上能够调用的静态方法和属性:

    class Demo extends React.Component {  static method = function(){    //doSomething  }  static propTypes = {    requiredFunc: React.PropTypes.func.isRequired  }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    //调用静态方法Demo.method()//调用属性Demo.propTypes
    • 1
    • 2
    • 3
    • 4

调用顺序及次数

如果你能理解上面所叙述的,那么,就不难得出下面的结论啦~~~

  1. getDefaultProps(),调用1次
  2. getInitialState(),调用1次
  3. componentWillMount(),调用1次
  4. render(),调用>=1次
  5. componentDidMount():仅客户端,调用1次
  6. componentWillReceiveProps(object nextProps),调用>=0次
  7. ShouldComponentUpdate(object nextProps, object nextState),调用>=0次
  8. componentWillUpdate(object nextProps, object nextState),调用>=0次
  9. render(),调用>=1次
  10. componentDidUpdate(object prevProps, object prevState),调用>=0次
  11. componentWillUnmount(),调用1次

好了,这次就写到这了,望与各君共勉。

参考资料:
https://facebook.github.io/react/docs/reusable-components.html#es6-classes
https://facebook.github.io/react/docs/component-specs.html


补充:

1.componentWillReceiveProps(nextProps)

关于这个componentWillReceiveProps存在一些误解。在互联网上有些教材声称这个函数只有当组件的props发生改变的时候才会被调用,其实是不正确的。实际上,只要是父组件的render函数被调用,在render函数里面被渲染的子组件就会经历更新过程,不管父组件传给子组件的props有没有改变,都会触发子组件的componentWill-ReceiveProps函数。

注意,通过this.setState方法触发的更新过程不会调用这个函数,这是因为这个函数适合根据新的props值(也就是参数nextProps)来计算出是不是要更新内部状态state。更新组件内部状态的方法就是this.setState,如果this.setState的调用导致component-WillReceiveProps再一次被调用,那就是一个死循环了。