浅析 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 的伎俩,或者设计哲学吧。怎么认为都行,我认为很有趣

相关文章

一、前言 在组件方面react和Vue一样的,核心思想玩的就是组件...
前言: 前段时间学习完react后,刚好就接到公司一个react项目...
前言: 最近收到组长通知我们项目组后面新开的项目准备统一技...
react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...