从父子组件系统理解React

网上很多资料都有关于React生命周期的内容,基本都是那几个钩子函数颠过去倒过来的讲解,但是这样起的作用是很小的,读完之后也就了解到钩子函数何时执行之类的。要真正的理解React声明周期,还需要从父子组件系统来理解,不能把生命周期的讲解只局限于单个组件。如下图:

 React组件生命周期函数调用顺序示意图

 React生命周期总体分为三步,分别为创建期、存活期、销毁期。创建期和销毁期比较好理解,主要就是在组件存活期,对视图更新的问题,即组件进行更新后带来的一系列周期函数是否调用及调用顺序的问题。

创建期

import ChildComponent from './Childcomponent'

export default class ParentComponent extends React.Component {
   render() {
      return (
         <div>
            <ChildComponent />
         </div>
      )
   }
}

如上面这段代码,父组件中引入子组件,当父组件被实例化时,会按照jsx语法,将ChildComponent进行实例化。从示意图中可以看到,当父组件的生命周期执行完render函数后,React会去实例化子组件,而子组件和孙组件之间的关系,和父组件与子组件的关系是一模一样的。当子组件的render函数执行完后,React会将Virtual DOM渲染为真正的DOM,然后依次执行componentDidMount函数。

 存活期

首先需要明确的是,在React中共有三种方式会导致更新视图 。一种是组件本身调用setState,一种是组件本身调用forceUpdate,还有另一种是父组件更新导致props改变。

创建期过后,创建函数不会再调用,但componentDidMount中的某些操作将常驻内存,比如绑定了事件,还有一些操作可以带来界面的更新,即在componentDidMount中调用this.setState。

react组件存活期的函数调用顺序示意图

最常发生的是父组件传递的props发生变化(父组件的render函数中),此时子组件会首先调用componentWillReceiveProps,这个函数的作用主要是在组件发生变化之前,对当前的state(甚至传递来的props,虽然不提倡)进行修改,即在这个函数内调用this.setState。但是非常重要的一点是,在componentWillReceiveProps中调用setState不会引起界面的重绘,无论父组件传递的props是否发生变化都会经过componentWillReceiveProps函数,只要父组件重新执行了render函数。

 另一种是调用setState,即在子组件自己内部调用this.setState,这时不会调用componentWillReceiveProps函数。因此非常明显的一点,当componentWillReceiveProps函数被调用时,明显是来自父组件的变化。

以上两种情况的更新,都会紧接着执行shouldComponentUpdate函数,这个函数非常重要,它决定了更新动作是否继续往下走(不熟悉生命周期流程的可以看我的另一篇博客)。如果返回false,那么就不会在执行下面的那些函数,当然,界面也不会被更新,因此,它是优化性能的关键。由于state和props的变化都会经过这里,所以它有两个参数:nextProps和nextState,它们各自对应不同的更新方式。

还有一种是在组件内调用this.forceUpdate,不需要经过shouldComponentUpdate,forceUpdate直接忽略shouldComponentUpdate,一定会更新组件。

销毁期 

我们开发的时候,几乎很少自己去销毁一个组件。组件的销毁隐匿于父组件的render函数中。当父组件执行render函数时,某些情况下,Virtual DOM中的某些节点经过diff,发现已经不存在了,因此会被销毁,而这个节点正好是一个组件的话,那么组件就会被销毁,而组件的componentWillUnmount方法会被调用。如下段代码:

   public render() {
      return (
         <div>
            {this.current ? null : <ChildComponent/>}
         </div>
      );
   }

 当父组件发生更新,而父组件的this.props.current为true时,ChildComponent这个组件就会被销毁,它的componentWillUnmount就会被调用。

猜你喜欢

转载自blog.csdn.net/qq_30104281/article/details/88531851