React源码解析:react-生命周期(初始化->更新阶段)

126 阅读4分钟

前言:

React生命周期,生命周期在类组件中是很重要的一部分知识点,学好且充分理解生命周期方法,可以对我们日常的开发中起到不可忽视的作用。函数组件自出现hooks以来,也可以优雅的使用hooks,弥补函数组件没有生命中周期的缺憾。

组件生命周期执行过程:

类组件生命周期的执行基本可以分为三个阶段:

  1. 初始化阶段
  2. 更新阶段
  3. 销毁阶段

这三个阶段的执行基本都在mountClassInstance和 updateClassInstance 这两个方法中执行的。

1、初始化阶段: 初始化阶段首先执行mountClassInstance方法用来实例化组件,constructor在此方法中被执行。在组件实例化后 便会调用mountClassInstance进行组件初始化。

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

参考文献:React实战进阶指南

getDerivedStateFromProps执行: getDerivedStateFromProps是初始化阶段执行的第二个生命周期,它是直接从ctor类上绑定的静态方法,传入props, state,返回值将和之前的state合并,作为新的state 传递给组件实例使用。

componentWillMount执行: 如果存在 getDerivedStateFromProps 和getSnapshotBeforeUpdate 就不会执行生命周期componentWillMount。

render函数执行: mountClassInstance函数到此阶段执行结束, updateClassInstance函数,在mountClassInstance执行完成后,执行render函数,生成了chuldren,react 即将调用reconcileChildren方法调和children。

componentDidMount执行: 在react调和完所有节点后,组件初始化进入commit阶段,会调用componentDidMount生命周期,

function commitLifeCycles(finishedRoot,current,finishedWork){ 
switch (finishedWork.tag)
    { /* fiber tag 在第一节讲了不同fiber类型 */ 
    case ClassComponent: { /* 如果是 类组件 类型 */ 
    const instance = finishedWork.stateNode /* 类实例 */ 
        if(current === null){ /* 类组件第一次调和渲染 */ 
        instance.componentDidMount() 
        }else{ 
        /* 类组件更新 */
        instance.componentDidUpdate(prevProps,prevStateinstance.__reactInternalSnapshotBeforeUpdate);
        } 
    } 
    }
}

componentDidMount和componentDidUpdate的执行时机是相同的,不同的是componentDidMount针对组件初始化componentDidUpdate针对的是组件再更新,到此初始化阶段,生命周期执行完毕。

执行顺序:constructor=>getDerivedStateFromProps或componentWillMount=> render=> componentDidMount。

2、更新阶段: 类组件在更新阶段,componentDidUpdate函数中 current 参数不为null,说明组件已经被挂载过了,就会按照更新逻辑处理。

function updateClassInstance(current,workInProgress,ctor,newProps,renderExpirationTime){
    const instance = workInProgress.stateNode; // 类组件实例
    const hasNewLifecycles = typeof ctor.getDerivedStateFromProps === 'function' // 判断是否具有 getDerivedStateFromProps 生命周期
    if(!hasNewLifecycles && typeof instance.componentWillReceiveProps === 'function' ){
        if (oldProps !== newProps || oldContext !== nextContext) { // 浅比较 props 不相等
            instance.componentWillReceiveProps(newProps, nextContext); // 执行生命周期 componentWillReceiveProps
       }
    }
    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' ){ /* 执行生命周期 shouldComponentUpdate 返回值决定是否执行render ,调和子节点 */ 
        shouldUpdate = instance.shouldComponentUpdate(newProps,newState,nextContext,);
    }
    if(shouldUpdate){ 
        if (typeof instance.componentWillUpdate === 'function') { 
        instance.componentWillUpdate(); /* 执行生命周期 componentWillUpdate */ }
        } 
    return shouldUpdate
}

componentWillReceiveProps执行: 判断getDerivedStateFromProps生命周期如果不存在,便开始执行componentWillReceiveProps生命周期,componentWillReceiveProps生命周期传入newProps和nextContext两个参数,

getDerivedStateFromProps执行: 返回值用于合并state,生成新的state。

shouldComponentUpdate执行: 传入新的props, state, context,返回值决定是否继续执行render函数,调和子节点(getDerivedStateFromProps的返回值可以作为新的state传递给shouldComponentUpdate)

render函数执行: render函数执行会得到一个新的React element元素,然后继续调和子节点。

getSnapshotBeforeUpdate执行:

function commitBeforeMutationLifeCycles(current,finishedWork){
    switch (finishedWork.tag) {
        case ClassComponent:{
            const snapshot = instance.getSnapshotBeforeUpdate(prevProps,prevState) /* 执行生命周期 getSnapshotBeforeUpdate */
            instance.__reactInternalSnapshotBeforeUpdate = snapshot; /* 返回值将作为 __reactInternalSnapshotBeforeUpdate 传递给 componentDidUpdate 生命周期 */
         }
    }
}

getSnapshotBeforeUpdate执行也在commit阶段,commit 分为beforeMutation阶段, Mutation阶段, Layout阶段,分别对对应,DOM修改前,DOM修改中, DOM修改后, 三个阶段。getSnapshotBeforeUpdate发生在beforeMutation阶段,生命周期的返回值将作为第三个参数 __reactInternalSnapshotBeforeUpdate 传递给componentDidUpdate生命周期。

componentDidUpdate执行: 到此生命周期,DOM完成修改,可以操作修改后的DOM,至此更新阶段的生命周期执行完毕。