react进阶第四讲——生命周期

类组件生命周期

当发现fiber tag = 1时,表示遇到类组件。

/* workloop React 处理类组件的主要功能方法 */
function updateClassComponent(){
    let shouldUpdate
    const instance = workInProgress.stateNode // stateNode 是 fiber 指向 类组件实例的指针。
     // instance 为组件实例,如果组件实例不存在,证明该类组件没有被挂载过,那么会走初始化流程
     if (instance === null) { 
        // 1. workInProgress 树,当前正在调和的 fiber 树 2. Component 就是项目中的 class 组件3. nextProps 作为组件在一次更新中新的 props 。
        constructClassInstance(workInProgress, Component, nextProps); // 组件实例将在这个方法中被new
        // renderExpirationTime 作为下一次渲染的过期时间。
        mountClassInstance(workInProgress,Component, nextProps,renderExpirationTime );  //初始化挂载组件流程。  
        // shouldUpdate 标识用来证明 组件是否需要更新。
        shouldUpdate = true;
     }else{  
        // 更新组件流程
        shouldUpdate = updateClassInstance(current, workInProgress, Component, nextProps, renderExpirationTime)
     }
     if(shouldUpdate){
         nextChildren = instance.render(); /* 执行render函数 ,得到子节点 */
         // current 树,在初始化更新中,current = null ,在第一次 fiber 调和之后,会将 workInProgress 树赋值给 current 树。
        reconcileChildren(current,workInProgress,nextChildren,renderExpirationTime) /* 继续调和子节点 */
     }
}

React 的大部分生命周期的执行,都在 mountClassInstance 和updateClassInstance 这两个方法中执行。

初始化阶段

function mountClassInstance(workInProgress,ctor,newProps,renderExpirationTime) {
    const instance = workInProgress.stateNode;
    const getDerivedStateFromProps = ctor.getDerivedStateFromProps; /* ctor 就是我们写的类组件,获取类组件的静态方法 */
    if (typeof getDerivedStateFromProps === 'function') {
        const partialState = getDerivedStateFromProps(nextProps, prevState); // 得到将被合并的state 
        const memoizedState = partialState === null || partialState === undefined ? prevState : Object.assign({}, prevState, partialState); // 合并state
        workInProgress.memoizedState = memoizedState;
        instance.state = workInProgress.memoizedState; // 就是我们在组件中 this.state获取的state
    }
    // 当 getDerivedStateFromProps 和 getSnapshotBeforeUpdate 不存在的时候 
    if(typeof ctor.getDerivedStateFromProps !== 'function' &&   typeof instance.getSnapshotBeforeUpdate !== 'function' && typeof instance.componentWillMount === 'function' ) {
        instance.componentWillMount(); 
    }
}

更新阶段

/**
* current: current 树,在初始化更新中,current = null ,在第一次 fiber 调和之后,会将 workInProgress 树赋值给 current 树。
* workInProgress: 当前正在调和的 fiber 树
* ctor: 就是我们写的类组件
**/
function updateClassInstance(current,workInProgress,ctor,newProps,renderExpirationTime) {
    const instance = workInProgress.stateNode;
    const hasNewLifecycles =  typeof ctor.getDerivedStateFromProps === 'function'
    if(!hasNewLifecycles && typeof instance.componentWillReceiveProps === 'function') {
        if (oldProps !== newProps || oldContext !== nextContext) {     // 浅比较 props 不相等
            instance.componentWillReceiveProps(newProps, nextContext);  // 执行生命周期  
         } 
    }
    let newState = (instance.state = oldState);
    if (typeof getDerivedStateFromProps === 'function')  {
        ctor.getDerivedStateFromProps(nextProps,prevState)  /* 执行生命周期getDerivedStateFromProps  ,逻辑和mounted类似 ,合并state  */
        newState = workInProgress.memoizedState;
    }
    let shouldUpdate = true    
    if(typeof instance.shouldComponentUpdate === 'function' ){
        shouldUpdate = instance.shouldComponentUpdate(newProps,newState,nextContext);
    }
    if(shouldUpdate){
        if (typeof instance.componentWillUpdate === 'function') {
            instance.componentWillUpdate(); /* 执行生命周期 componentWillUpdate  */
        }
    }
    return shouldUpdate
}

react进阶第四讲——生命周期

  • 初始化阶段:constructor -> getDerivedStateFromProps / componentWillMount -> render -> componentDidMount
  • 更新阶段:componentWillReceiveProps( props 改变) / getDerivedStateFromProp -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate
  • 卸载阶段:componentWillUnMount
  1. constructor:
  • 在类组件创建实例时调用,而且初始化的时候执行一次,所以可以在 constructor 做一些初始化的工作。
  1. getDerivedStateFromProps:
  • 代替 componentWillMount 和 componentWillReceiveProps
  • 组件初始化或者更新时,将 props 映射到 state。
  • 返回一个对象来更新 state,如果返回 null 则不更新任何内容。
getDerivedStateFromProps(nextProps,prevState)

getDerivedStateFromProps 方法作为类的静态属性方法执行,内部是访问不到 this。

  1. componentWillUpdate 后期版本作废,不要使用
  2. getSnapshotBeforeUpdate
  • 配合componentDidUpdate 一起使用,计算形成一个 snapShot 传递给 componentDidUpdate 。保存一次更新前的信息。
getSnapshotBeforeUpdate(prevProps,preState) { return xxx}

函数组件生命周期

  1. useEffect
useEffect(()=>{
    const subscription = props.source.subscribe();
      return () => {
        // 清除订阅
        subscription.unsubscribe();
      };
},dep)

useEffect(()=>{
    return destory
},dep)
  • useEffect 第一个参数 callback,返回的destory作为下一次callback执行之前调用,用于清除上一次 callback 产生的副作用。在执行下一个 effect 之前,上一个 effect 就已被清除。
  • 第二个参数作为依赖项,是一个数组,可以有多个依赖项,依赖项改变,执行上一次callback 返回的 destory ,和执行新的 effect 第一个参数 callback 。
  • 对于 useEffect 执行, 采用异步调用 ,对于每一个 effect 的 callback, 会被放入任务队列,等到主线程任务完成才执行。所以effect回调函数不会阻塞浏览器绘制视图。
  1. useLayoutEffect
  • useLayoutEffect采用了同步执行, 是在DOM 绘制之前执行。
  • useLayoutEffect callback 中代码执行会阻塞浏览器绘制。

Q: useEffect和 componentDidMount / componentDidUpdate 执行时机有什么区别 ?

A: useEffect是异步执行, 不会阻塞浏览器绘制。componentDidMount / componentDidUpdate 是同步执行的

如何使用useEffect替代componentDidMount?

A:

React.useEffect(()=>{
    /* 请求数据 , 事件监听 , 操纵dom */
},[])  /* 切记 dep = [] */

ß

上一篇:vue性能优化-分片添加数组


下一篇:WebApi设置HttpContext.Current.User