浅析 React 生命周期

Overview

近来常有进修React相干的手艺,写了几个React的小Demo,运用 React/Express 手艺栈。着实太小,羞于拿出来细说。React 的确是一个值得跟随的手艺。但React系统着实巨大,我现在仅略知一二。这里要挑出来说的,是React的性命周期机制。Demo的进修历程当中,对它的轻易、易用的地方着实是深有体会,在一些细节处也值得推敲,在这里做一下纪录,便于分享。

假如你打仗过React,也许对rendercomponentWillMount等,会相对的熟习,由于它们再经常使用不过。但用归用,个中的一些理论上的细节,每每轻易在运用的历程当中被疏忽,使我们多敲了不少代码,心很累的 : )

浅显来说,React 将组件 component 在web中的构成、修正和衬着等划分为多少个阶段,构成组件的性命周期。在一个完全的性命周期内,一个组件会经由多少个阶段,在迥殊的阶段组件会挪用一个迥殊的lifecycle method,即性命周期要领。以下:

  1. constructor(props)

  2. componentWillMount()

  3. render()

  4. componentDidMount()

  5. componentWillReceiveProps(nextProps)

  6. shouldComponentUpdate(nextProps, nextState)

  7. componentWillUpdate(nextProps, nextState)

  8. render( )* //明白上与3. render()略有差别,见下。

  9. componentDidUpdate(prevProps, prevState )

  10. componentWillUnmount( )

值得注重,这些性命周期是React 内置的,在特定条件下就会被挪用。而开辟者能够做的就是 override(重载)这些要领,以完成想要的功用。

constructor

constructor(props),组件构成时挪用。

constructor 函数可明白为组件的组织函数,从组件的类(class) 实例化一个组件实例。这个函数在组件构成时被挪用,是一切性命周期函数中最早实行的。在constructor函数内,若有必要,举行state的初始化以及绑定要领;不然能够省去constructor函数的声明。

有以下几点在开辟时值得注重:

  1. constructor 函数内,在实行任何statement之前,必需是super() 函数,假若有参数须将参数带上。这点跟Java很像。

  2. 在constructor 函数内,this.props 返回 undefined

  3. 不要在初试化state时援用props 里的值,不然每当props更新时,都须要在componentWillReceiveProps 函数内对state举行更新。(同时这也涉及到组件state拔取的准绳,若有须要请浏览Thinking in React

class App extends Component {
  constructor(props) {
    super(props);//------------(1)
    console.log(this.props);// undefined ------------(2)
    //initialize the state
    this.state = {
      value: '',
      color: props.initialColor  // 不可取  ------------(3)
    }
    //bind methods
    this.handleClick = this.handleClick.bind(this);
  }
}

componentWillMount

componentWillMount(),在组件初次衬着(render)之前挪用。

mount装置之意,我们能够明白为组件初次被加载在web中。因而每次页面加载/革新,或许某个组件第一次加载进入web时能够挪用componentWillMount( ) 函数。举个例子,在初次进入文章列表常常,可在 componentWillMount 对一切文章举行查询。如许,在render之前,就可以拿到一切文章的数据,以便在render中运用。

在componentWillMount ( ) 函数内,若对this.state举行更新,没法触发从新衬着组件。

class PostList extends Component {
  //...
  //在componentWillMount 组件内猎取一切博客列表
  componentWillMount(){
    axios.get('/posts')
         .then(res=>{
           //...
         });
  }
  //在 render 函数内将拿到的博客列表 衬着在页面中
  render(){
    //...
  }
}

Render

render()

render 即 衬着函数,是编写组件代码时,唯一一个必需的函数。该函数须有返回值,返回一个组件,即终究衬着出来的组件。在运用组件的class举行组件实例化时,获得的就是其返回值。

返回值有两种范例:

  1. 一个父标签,这个父标签内能够包括多少个子标签,在最外层标签必需只要一个。

  2. false 或许 null,代表不衬着任何DOM

class App extends Component {
  //...
  render(){
    return (
      <div>
          //...
      </div>
    )
  }
}

注重:在render函数中只做与返回组件相干的事情,勿在个中对state举行操纵,能够保证每次挪用render函数,返回的组件都是雷同的。不然将加大项目保护本钱。

别的,假如shouldComponentUpdate函数返回false,则不实行render函数。关于shouldComponentUpdate将在下面引见。

componentDidMount

componentDidMount(),一旦组件初次加载完成,便会挪用

假如须要对衬着出来的DOM节点做任何操纵,能够在此处举行。(提醒: this.refs 可猎取实在DOM)。

在该组件内设置state将会致使组件被从新衬着。

class App extends Component {
  //..
  componentDidMount(){
    //将会触发组件从新衬着
    this.setState({
      value: '100'
    }):
    //对节点举行操纵
      this.refs.div.appendChild(newChild);
  }
  
}

上面临 React性命周期函数中的constructor / componentWillMount / render / componentDidMount 四个函数举行了引见。下面将继承引见别的5个要领。在此之前,先总结一下,下面列表中列出的3.render()8.render()的在逻辑上的区分和联络。先上一个列表。

  1. constructor(props)

  2. componentWillMount( )

  3. render( )

  4. componentDidMount( )

  5. componentWillReceiveProps(nextProps)

  6. shouldComponentUpdate(nextProps, nextState)

  7. componentWillUpdate(nextProps, nextState)

  8. render()*

  9. componentDidUpdate(prevProps, prevState)

  10. componentWillUnmount()

「两个」render( )要领的区分

3.render( ) 与 8.render( )*

实质上,这两个要领毫无区分。但这里为何要说起它们之间的区分呢?实在,它们只是统一函数 render( ) 在组件性命周期的两个差别阶段的差别明白罢了。

前一个 render( ) 要领指在组件第一次被加载进入页面时,挪用的 render( ) 要领;后一个则指撤除第一次,以后挪用的 render( ) 要领。

因而,我们更情愿称第一次的 render( ) 要领为 mount( 装置 ),称后一个 render( ) 要领为 re-render ( 从新衬着 ) 。这也是为何组件初次 render 前后的要领名中带有mount一词的原因了。

这是 React 的手法,或许设想哲学吧。怎样以为都行,我以为很风趣?

下面引见的要领,都是缭绕第二个 render( ) ,即从新衬着 re-render 睁开的。

componentWillReceiveProps

componentWillReceiveProps(nextprops)已加载的组件在 props 发作变化时挪用。

假如须要经由过程监听 props 的转变来修正 state 的值,则能够经由过程重载该函数完成。

须要注重,在有些状况下,组件的 props 未发作转变也会挪用该函数。因而假如在该函数内的逻辑,只是想捕捉当前 props 与 吸收的 nextProps 的差别来做出一些操纵,则最好先将 props 与 nextProps 举行比较。

1.在mounting阶段,即初次 render ,不挪用 componentWillReceiveProps 要领。明白了两个 render( ) 的差别,便晓得这里是为何了。

2.this.setState({…}) 不触发 componentWillReceiveProps 要领。由于该要领只监听 this.props 的转变,不关心 this.state 值的变化。

class App extends Component {
  componentWillReceiveProps(nextProps){
    //吸收的色彩 与 当前色彩差别时
    if (this.props.color !== nextProps.color){
      ...
    }
  }
}

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState)

返回 true orfalse

要不要更新(从新衬着)组件?浅显易懂。这个要领的返回值决议了,当 props 或许 state 值发作变化时,组件是不是从新衬着。两种状况:

  1. 返回true,从新衬着。紧接着,继承实行 componentWillUpdate()render()componentDidUpdate()

  2. false,不从新衬着。不再实行任何性命周期函数函数(亦不实行该组件的 render( ) 函数)。然则,并不阻碍其子组件。也就是说,假如其子组件的 props 或 state 发作转变时,只会取决于谁人组件的 shouleComponentUpdate ( ) 要领的返回值。原理虽懂,但碰到是可能会犯含糊,由于开辟中常常会碰见组件嵌套的状况,父子组件之间通报统一套 props 或 state,一来二去,谁更新谁不更新,轻易含糊,须要细致咯。

  1. 在绝大部分状况下,当 props 或 state 转变时,都是须要从新衬着组件的。

  2. 注重,依据 React 官方 的说法,就算 shouldComponentUpdate( ) 要领返回 false,组件也会从新衬着。须要随时注重官方文档的变化。

class PostList extends Component {
  shouldComponentUpdate(nextProps, nextState){
    //return true;默许
    return false;// 不更新组件
  }
}

componentWillUpdate

componentWillUpdate(nextProps, nextState),当 shouldComponentUpdate( ) 要领返回 true 后挪用。

这个要领供应了一个为从新衬着作预备的时机,意义是要在这里,趁接下来的 render( ) 要领从新衬着之前,完成该完成的操纵。这个要领在 mount 阶段不会被挪用,只在 re-render 阶段被挪用。

注重,不要在该要领内挪用 this.setState({…}),若有须要,请在 componentWillReceiveProps( ) 要领中完成。养成优越的编程范例。

class App extends Component {
  componentWillUpdate(nextProps, nextState){
    var isLate = this.nextProps.isLate;
    if(isLate){
      //...
    } else {
      //...
    }
  }
}

componentDidUpdate

componentDidUpdate(prevProps, preState),一旦组件初次更新(从新衬着)完成时挪用。

因而像 componentDidMount( ) 一样,假如须要对衬着出来的DOM节点做任何操纵,能够在此处举行。(提醒: this.refs 可猎取实在DOM)。

在该组件内设置state将会致使组件被从新衬着。

class App extends Component {
  //..
  componentDidUpdate(){
    //将会触发组件从新衬着
    this.setState({
      value: '100'
    });
    //对节点举行操纵
    this.refs.div.appendChild(newChild);
  }
  
}

componentWillUnmount

componentWillUnmount(),在组件即将被卸载(或烧毁)之前挪用。

在这个要领中,适合做一些清算善后事情。比方清晰timer,作废收集要求,或许消灭在 componentDidMount 或 componentDidUpdate 中天生的相干 DOM 节点。

总结

  1. mountre-render 的是有区分的。

  2. mount阶段运用前一部分的四个要领( constructor / componentWillMount / render / componentDidMount),缭绕组件初次加载而挪用;

  3. 后一部分 re-render 相干的,运用 componentWillReceiveProps / shouldComponentUpdate / componentWillUpdate / render / componentDidUpdate ,缭绕组件从新衬着而挪用。

我总结了一张流程图和一个表格,以示意这些周期函数之间的关联,以及在何种状况下会挪用这些函数。

注重:componentWillUnmount 要领未包括个中。

《浅析 React 生命周期》

mountprops 变化state 变化
constructorcomponentWillReceivePropsshouldComponentUpdate
componentWillMountshouldComponentUpdate(return true) ⏬ / 完毕
render(return true) ⏬ / 完毕componentWillUpdate
componentDidMountcomponentWillUpdaterender
/rendercomponentDidUpdate
/componentDidUpdate/

完。

文章为本人原创,原文见本人个博:
浅析「React」性命周期(一)
浅析「React」性命周期(二)

    原文作者:MysticSheep
    原文地址: https://segmentfault.com/a/1190000008325023
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞